/*
   * Вычисление количества позиций символов для
   * символьного представления неотрицательного
   * 32-битового целого числа

   * Пограмма содержательно эквивалентна программе task1.c

   * Ассемблирование:  as -ahlsm=task1.lst --32 -gstabs+ -o task1.o task1.S
   *
   * -ahlsm ключи полного листинга
   * task1.lst - имя ТЕКСТОВОГО файла листинга, описывающего
   * результат ассемблирования

   * --32 - генерировать 32 разрядные машинные команды

   * -gstabs+ - ключи генерации отладочной информации для отладчика

   * -o task1.o - задание имени выходного ( для команды as -
   * объектного) файла

   * -o ключ определения имени выходного ( для команды as -
   * объектного) файла

   * task1.S -  исходный -  входной файл (этот файл)
   *
   * Редактирование связей: ld -melf_i386 -o task1-exe-S task1.o

   * МОЖНО НЕ ЧИТАТЬ! В нашем курсе используется только
   *                -melf_i386
   *  -m<эмуляция ld> ld может генерировать машинный код
   *     исполняемого файла для нескольких архитектур.
   *     Говорят, что ld "эмулирует" архитектуру.
   *  Поддерживаемые архитектуры - "эмуляции":

   *    elf_x86_64
   *    elf_i386
   *    i386linux
   *    elf_l1om

   * -o task1-exe-S - задание имени выходного
   * (для команды ld -  исполняемого) файла

   * -o ключ определения имени выходного
   * (для команды ld -  исполняемого) файла

   * task1.o - объектный файл (входной для редактора связей ld)

   * Запуск отладчика: kdbg task1-exe-S
   *
*/

.include "my-macro"  # подключение файла с макроопределениями


.data     # секция данных, распределение памяти
          # соотв. конструкция языка C и коммент.
n:     .long 2345         # int n = 2345; число
length: .long 0           # int length =0; результат
ten:     .long 10         # определяем константу ЯВНО
                          # нет аналога в C

.text # секция команд процесора

.global _start     # точка входа - глобальная метка

_start:
    nop             # пустая операция - no operation

#   нужна, чтобы задать отладчику контр. точку останова на следующей, первой 
#   содержательной команде программы

    movl $0, %ebx   # counter = 0; счетчик делений
    movl n, %eax    # готовим к команде деления idivl
                    # нет аналога в C
nextdigit:
        movl  $0, %edx          # еще готовим, уже в цикле
                                # нет аналога в C

#   Смысл этой подготовки.
#   Примем, что делим 32 битовое число, размещннное в EAX.
#   Т.к. команда idivl интерпретирует значения в паре регистров EDX,EAX
#   как единое 64 битовое делимое, то перед делением EDX должен иметь значение 
#   0.  После выполнения эта команда
#   помещает в EDX - остаток, в EAX - частное, что
#   НАРУШАЕТ ИНТЕРПРЕТАЦИЮ значений пары EDX,EAX. Перед следующим делением эту 
#   интерпретацию надо восстановить, присвоив EDX значение 0.

        idivl ten        # делим объединенные регистры edx:eax на 10
                         # частное в  eax, остаток в edx

        incl %ebx        # ++counter; счетчик делений + 1

#    две следующие команды соответствуют условному оператору if (quotient) goto 
#    nextdigit;

        cmpl $0, %eax    # частное > 0 ?
        jg   nextdigit   # ДА, продолжаем


/* 

проверка условия на ЯКЦП ВСЕГДА выполняется парой команд:

   cmp <операнд1>, <операнд2> - вып. вычитание <операнд2>-<операнд1>
                          - отражает знак и др. свойства результата
                            в битах регистра флагов.

   jcc <операнд> - j[ump on] c[ondition] c[ode] проверяет
          условие в битах регистра флагов и по результату проверки
          выполняет/не выполняет переход  по адресу <операнд>.

 В нашем случае команда jg   nextdigit { jg - jump if greater
- перейти если строго  больше} выполняет переход на метку
nextdigit: если предыдущая команда cmpl $0, %eax установила в
регистре флагов биты, указывающие, что значение в регистре %eax,
т.е. частное, СТРОГО  БОЛЬШЕ нуля.

*/

        movl %ebx, length  # length = counter; ДА,сохраняем результат

    Finish                 # конец работы,
                           # возврат в ОС
                           # (макро из файла my-macro)

.end   # последняя строка исходного текста
       # as прекращает чтение файла исходного текста
       