Ассемблер
Как вывести число в ассемблере
Чтобы вывести число в ассемблере, его обычно сначала преобразуют в строку. Процессор хранит число как бинарное значение в регистре, а экрану или консоли нужны символы: '0', '1', '2' и так далее. Поэтому вывод числа состоит из двух частей: преобразовать число в десятичные цифры и передать эти символы функции вывода
Почему нельзя просто вывести регистр
Если в eax лежит число 123, внутри регистра это не строка "123". Это бинарное значение. Консоль не знает, что нужно показать именно три символа 1, 2, 3. Эту работу должен сделать ваш код или библиотечная функция
Базовый алгоритм
Для положительного числа:
если число = 0:
вывести '0'
иначе:
пока число > 0:
остаток = число % 10
сохранить символ '0' + остаток
число = число / 10
вывести сохраненные символы в обратном порядке
Почему в обратном порядке? Потому что деление на 10 сначала дает последнюю цифру
Для числа 123:
123 % 10 = 3
12 % 10 = 2
1 % 10 = 1
Получили 3, 2, 1, а выводить нужно 1, 2, 3
Ассемблерная логика
В x86 для деления используется div. Упрощенно:
; eax = число
; делим на 10
; остаток окажется в edx
; частное останется в eax
Перед div нужно подготовить регистры. Для беззнакового 32-битного деления обычно очищают edx:
xor edx, edx
mov ebx, 10
div ebx
После этого edx содержит остаток от деления на 10. Чтобы превратить цифру в символ, прибавляют '0':
add dl, '0'
Где хранить цифры
Удобно подготовить буфер и заполнять его с конца. Тогда цифры, которые получаются в обратном порядке, сразу лягут правильно
buffer: [ ... ... ... ... ]
пишем последнюю цифру в конец
потом следующую левее
После цикла выводим только заполненную часть буфера
Ноль и отрицательные числа
Ноль нужно обработать отдельно, потому что цикл «пока число больше нуля» не запишет ни одной цифры
Отрицательные числа требуют знака -. Обычно сначала проверяют знак, выводят или сохраняют минус, затем работают с модулем числа
Частые ошибки
Не очищают edx перед div
Для 32-битного деления edx:eax образуют делимое. Если edx содержит мусор, результат будет неверным или возникнет ошибка деления
Выводят цифры в обратном порядке
Остатки появляются справа налево. Их нужно перевернуть или записывать буфер с конца
Забывают про число 0
Ноль нужно вывести как символ '0', а не как пустую строку
Путают число и символ
Цифра 5 и символ '5' — разные значения. Для символа нужно прибавить '0'
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- Как в ассемблере преобразовать строку в число
- CMP в ассемблере
- CMP в ассемблере: как работает сравнение
- CMP, JMP, JE, JNZ: условия и циклы в ассемблере
Как проверить результат на практике
Для ассемблера важно сначала понять, под какую среду написан пример: DOSBox/TASM, Linux x64/NASM, Visual Studio/MASM или микроконтроллер. Один и тот же смысл может записываться разным синтаксисом, поэтому не переносите команды между средами вслепую. Создайте отдельную папку для примера, сохраните файл с расширением .asm, выполните сборку именно тем инструментом, который указан в уроке, и сравните вывод или состояние регистров с ожидаемым результатом
Если пример не собирается, читайте первую ошибку ассемблера: обычно она указывает на строку, неизвестную инструкцию, неверную метку, неправильную секцию или конфликт синтаксиса. Исправляйте одну ошибку за раз. В ассемблере это особенно важно, потому что маленькая опечатка в метке, регистре или размере операнда может полностью изменить поведение программы