Как вывести число в ассемблере
Перейти к содержимому

Как вывести число в ассемблере

Как вывести число в ассемблере

Кто-нибудь подскажите как на экран вывести число в Ассемблере

Например такой код:
mov AX,6
add AX,5

как вывести результат находящийся в AX

(Если из АХ совсем никак, то хотябы используя переменную, мне важно просто посмотреть результат арифметических действий)

Пользователь
Регистрация: 25.08.2008
Сообщений: 51

попробуй так.
Ассемблбер давно забросил, так что не полностью уверен в правельности

mov bx, ax
mov ah, 09h
mov dx, bx
int 21h

Последний раз редактировалось Slicker; 25.08.2008 в 12:54 .
Регистрация: 09.01.2008
Сообщений: 26,238

нет, так не получится!
функция 09 int 21 выводит строку, адрес которой в dx:

.model small .code F3 db 13,10, ' Hello, World$' start: push cs pop ds mov ah,09h lea dx, F3 int 21h exit: mov ah, 4ch int 21h end start

если надо вывести один символ, то можно воспользоваться функцией 02 int21
а вот как вывести содержимое регистра AX — я затрудняюсь подсказать. ;-(

Serge_Bliznykov
Посмотреть профиль
Найти ещё сообщения от Serge_Bliznykov

добрый няша
Регистрация: 29.10.2006
Сообщений: 4,804

для вывода числа, надо сначала преобразовать его в строку, а потом вывести.
уже обсуждалось http://programmersforum.ru/showthread.php?t=20070

[Программирование на ассемблере на платформе x86-64]

Как вывести число в ассемблере

На этом шаге мы приведем текст процедур, позволяющих вводить с клавиатуры и выводить на экран многозначные числа.

Приведем тексты процедур, которые можно использовать для организации ввода и вывода многозначных чисел. Эти процедуры можно взять за основу при разработке собственных аналогичных процедур.

Дадим краткое описание алгоритмов, использованных при реализации этих процедур.

Процедура ввода принимает символ с клавиатуры и помещает его в стек, увеличивая на единицу значение регистра CX , сохраняющего количество введенных символов. После нажатия пользователем клавиши Enter , из стека извлекается очередная цифра, которая умножается соответственно на 1, 10, 1000 и т.д. Полученное значение прибавляется к результату, находящемуся в регистре BX . Эти операции осуществляются в цикле.

Например, если было введено число 124, то тело цикла будет выполнено 3 раза и при извлечении цифр из стека будет вычислена такая сумма: 4*1+2*10+1*100, что составляет 124.

Процедура позволяет вводить отрицательные числа. В этом случае знак ‘-‘ будет последним в стеке, что является признаком завершения цикла.

Процедура вывода числа осуществляет деление значения, находящегося в регистре BX , на 10 и размещение в стеке остатков от деления. После того, как получившееся на очередном шаге частное стало равно нулю, осуществляется извлечение из стека находящихся там символов и вывод их на экран.

При выводе отрицательного числа сначала выводится знак ‘-‘, берется соответствующее этому отрицательному положительное число и далее выполняется описанный алгоритм.

Приведем текст модуля, содержащего описанные процедуры.

PUBLIC Vvod,Vyvod ;Экспортируемые процедуры. ;------------------Сегмент стека ------------------- StackSg SEGMENT PARA Stack 'Stack' DW 132 DUP (?) StackSg ENDS ;------------------Сегмент кодов ------------------- CodeSg SEGMENT PARA PUBLIC ASSUME CS:CodeSg Vvod PROC FAR ;Процедура ввода числа. ;Число помещается в регистр BX. ;------------------ Сохранение регистров -------------- PUSH AX PUSH CX PUSH DX ;------------------ Ввод с клавиатуры ----------------- MOV BX,0000 ;Введенное число. MOV CX,0000 ;Количество помещений в стек. MOV DX,1 ;Множитель. @V1: MOV AH,01 INT 21H CMP AL,0DH ;Это клавиша Enter? JE @V2 ;Переход на обработку числа. CMP AL,'-' ;Это знак '-'? JE @V3 ;Ничего вычитать не надо. SUB AL,30H @V3: MOV AH,0 PUSH AX ;Поместить цифру в стек. INC CX ;Увеличить счетчик на 1. JMP @V1 ;Переход на ввод новой цифры. ;------------------ Получение числа -------------------- @V2: POP AX ;Достать цифру из стека. CMP AL,'-' ;Это '-'? JNE @V4 ;Нет - перейти на обработку. NEG BX ;Да - сменить знак числа. JMP @V5 ;Выход из процедуры. @V4: MUL DL ;Умножить ее на множитель. ADD BX,AX ;Прибавить произведение к результату. ;Получить очередной множитель. MOV AX,DX MOV DX,000AH MUL DL MOV DX,AX ;Поместить множитель в DX. LOOP @V2 ;Извлечь очередную цифру. ;-- Выход из процедуры. Восстановление регистров -------- @V5: POP DX POP CX POP AX RET Vvod ENDP Vyvod PROC FAR ;Процедура вывода числа на экран. ;Число находится в регистре BX. ;------------------ Сохранение регистров -------------- PUSH AX PUSH CX PUSH DX ;------------------ Проверяем знак числа -------------- CMP BX,0 JGE @K1 ;Да - число неотрицательное. MOV AH,02 ;Выводим на экран символ '-'. MOV DL,'-' INT 21H NEG BX ;Меняем знак. ;------------------ Получаем цифры числа --------------- @K1: MOV AX,BX MOV BX,0000 MOV DX,000AH;Делитель. MOV CX,0000 ;Количество помещений в стек. @K2: DIV DL MOV BL,AH ;Остаток от деления - в стек. PUSH BX MOV AH,0 INC CX ;Увеличить счетчик на 1. CMP AX,0 JNE @K2 ;Получение следующей цифры. ;------------------ Вывод цифр на экран ----------------- MOV AH,02 @K3: POP DX ADD DL,30H INT 21H LOOP @K3 ;-- Выход из процедуры. Восстановление регистров -------- POP DX POP CX POP AX RET Vyvod ENDP CodeSg ENDS END

Текст этого модуля можно взять здесь.

Понятно, что эти процедуры далеки от совершенства. Они могут послужить основой для написания полнофункциональных процедур.

Отметим, что можно добавить к этим процедурам еще несколько процедур (например, процедуры очистки экрана, установки курсора, вывода строки на экран и т.д.) и оформить их в виде файла, который присоединять к файлу с программой на этапе компоновки при выполнении, например, следующей команды:

LINK.EXE PROG.OBJ + SERVIS.OBJ .

Здесь PROG.OBJ — откомпилированный файл с основной программой, SERVIS.OBJ — откомпилированный файл с набором процедур.

Отметим также, что крайне желательно в создаваемых процедурах сохранять используемые в процедуре регистры в начале и восстанавливать их в конце процедуры. Это позволит при разработке основной программы не вспоминать, какие регистры были задействованы в реализации той или иной процедуры.

На следующем шаге мы приведем несколько примеров использования операторов условного перехода .

Вывод на экран Assembler

Вывод на экран Assembler

Сегодня мы рассмотрим тему «Вывод на экран Assembler» и разберем программу, которая сможет выводить на экран нашей консоли числа. Для этого нам потребуется изучить несколько новых процедур, а также познакомится с подключаемыми библиотеками и системными файлами.

Вспомним о процедурах

Для начала, я напомню вам, что когда мы изучали с вами процедуры Assembler, то я, подводя итоги, написал, что для процедур с параметрами необходим прототип. Да, это так, но есть одно но: если эта процедура не является стандартной, и не описана где нибудь в подключаемой библиотеки. Так вот, ранее изученная процедура ExitProcess, а также те процедуры, которые мы сегодня с вами изучим(WriteConsoleA, wsprintf) являются стандартными(на самом деле такого термина нет, но думаю так понятнее), и для них не нужно писать прототип.

Вывод на экран

А теперь перейдем к коду:

.386 .model flat,stdcall option casemap:none include ..\INCLUDE\kernel32.inc include ..\INCLUDE\user32.inc includelib ..\LIB\kernel32.lib includelib ..\LIB\user32.lib

Как вы заметили, у нас увеличилось число подключаемых файлов. И как я уже выше написал, все они понадобятся для того, чтобы работали процедуры, которые мы будем использовать далее в этой программе.

BSIZE equ 15 ; так задается константа BSIZE .data ifmt db "%d", 0 ;строка формата buf db BSIZE dup(?) ;буфер msg dd 123456 ;то что мы выводим stdout dd ? cWritten dd ?

Далее будет не очень понятно пока не увидим в действии, но все же попробую объяснить. Первое, что мы делаем, объявляем константу BSIZE со значением 15. Затем в разделе .data , там где объявляются переменные, задаем несколько переменных, которые потребуются как параметры для наших дальнейших процедур. Стоит отметить переменную buf: запись dup(duplication) говорит о подряд идущих байт, которые выделяются под переменную buf размерностью BSIZE(15). А знак вопроса говорит, что значения байт заранее не определено. Итак, пока не все понятно, поэтому идем дальше, тут у вас должен сложиться пазл:

.code start: invoke GetStdHandle, -11 ; дескриптор вывода mov stdout,eax ; по умолчанию помещается в eax invoke wsprintf, ADDR buf, ADDR ifmt, msg invoke WriteConsoleA, stdout, ADDR buf, BSIZE, ADDR cWritten, 0 invoke ExitProcess,0 end start

Для того, чтобы вывести что нибудь на экран нужно знать дескриптор вывода. Процедура GetStdHandle считывает адрес дескриптора экрана, и по умолчанию записывает его в регистр eax. После, мы записываем это значение из регистра в переменную stdout. Дальше мы используем процедуру wsprintf. Она нужна для того, чтобы вывести наше сообщение(именно число) в понятном для нас формате, то есть эта процедура преобразования машинного языка в человеческий формат. Для этого используется переменная ifmt. Ну и за сам вывод отвечает процедура WriteConsoleA. Она принимает 5 параметров, и последним всегда должен идти 0. Мой совет: лучше запомнить эти процедуры в таком виде, каком они представлены здесь, в наших дальнейших статьях мы практически всегда будем их использовать.

Запуск программы

А сейчас я покажу вам как все это реализовать на практике, после написания кода.
Я создал файл fifth.asm и поместил его в папку BIN. Затем я открываю командную строку, и перехожу в папку BIN с помощью команды cd C:\Users\Никита\BIN (у вас будет другой путь, скорее всего)
Далее компилирую наш файл, прописывая команду amake.bat fifth, если код правильный, то будет как на фото: Assembler-4Как мы видим, все скомпилировалось без ошибок, но ничего не вывелось на экран. Для того, чтобы наша программа выполнилась, нужно после компиляции запустить файл с расширением .exe(он создается автоматически после правильной компиляции). Прописываем в командной строке fifth.exe, у вас должно получится нечто подобное:
Assembler-5Все прошло успешно! На сегодня на этом закончим c выводом на экран, но в следующих примерах Assembler мы еще будем возвращаться к этой теме, если у вас остались вопросы, то пишите их в комментариях, не забывайте просматривать исходники и предыдущие статьи. Скачать исходники

Поделиться ссылкой:

20. Вывод чисел на консоль в ассемблере i8086

В качестве параметра ей передаётся адрес строки в регистре DI. Строка должна оканчиваться символом ‘$’. Здесь используется команда XCHG , которая выполняет обмен значениями двух операндов. Вторая полезная процедура — вывод конца строки. Она вызывает первую процедуру для вывода двух символов CR(13) и LF(10). Вызывается без параметров и не изменяет регистры.

;Процедура вывода конца строки (CR+LF) print_endline: push di mov di,endline ;DI = адрес строки с символами CR,LF call print_str ;Вывод строки на консоль pop di ret . endline db 13,10,'$'

Вывод чисел в двоичном виде

Алгоритм вывода в двоичном виде очень прост. Нужно проанализировать все биты числа и поместить в строку символы ‘0’ или ‘1’ в зависимости от значения соответствующего бита. Удобно делать это с помощью циклического сдвига в цикле. Сдвинутый бит оказывается в флаге CF, а после завершения цикла в регистре то же значение, что и в начале. Процедура byte_to_bin_str преобразует байт в регистре AL в строку. Адрес буфера для строки передаётся в регистре DI. Процедура всегда записывает в буфер 8 символов, так как в байте 8 бит.

;Процедура преобразования байта в строку в двоичном виде ; AL - байт. ; DI - буфер для строки (8 символов). Значение регистра не сохраняется. byte_to_bin_str: push cx ;Сохранение CX mov cx,8 ;Счётчик цикла btbs_lp: rol al,1 ;Циклический сдвиг AL влево на 1 бит jc btbs_1 ;Если выдвинутый бит = 1, то переход mov byte[di],'0' ;Добавление символа '0' в строку jmp btbs_end btbs_1: mov byte[di],'1' ;Добавление символа '1' в строку btbs_end: inc di ;Инкремент DI loop btbs_lp ;Команда цикла pop cx ;Восстановление CX ret ;Возврат из процедуры

Используя эту процедуру, легко написать ещё одну для вывода слова в двоичном виде:

;Процедура преобразования слова в строку в двоичном виде ; AX - слово ; DI - буфер для строки (16 символов). Значение регистра не сохраняется. word_to_bin_str: xchg ah,al ;Обмен AH и AL call byte_to_bin_str ;Преобразование старшего байта в строку xchg ah,al ;Обмен AH и AL call byte_to_bin_str ;Преобразование младшего байта в строку ret

И наконец вот две процедуры, которые делают то, что нужно. Буфер имеет размер 17 символов, так как в слове 16 бит + символ ‘$’ , обозначающий конец строки.

;Процедура вывода байта на консоль в двоичном виде ; AL - байт print_byte_bin: push di mov di,buffer ;DI = адрес буфера call byte_to_bin_str ;Преобразование байта в AL в строку mov byte[di],'$' ;Добавление символа конца строки sub di,8 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;Процедура вывода слова на консоль в двоичном виде ; AX - слово print_word_bin: push di mov di,buffer ;DI = адрес буфера call word_to_bin_str ;Преобразование слова в AX в строку mov byte[di],'$' ;Добавление символа конца строки sub di,16 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret . buffer rb 17

Результат работы программы выглядит вот так:

Вывод чисел в шестнадцатеричном виде

Этот пример по структуре похож на предыдущий, поэтому для краткости я рассмотрю только сами процедуры преобразования числа в строку. Преобразование в шестнадцатеричный вид удобно выполнять группами по 4 бита, то есть по тетрадам. Каждая тетрада будет представлять собой одну шестнадцатеричную цифру. Я написал отдельную процедуру для преобразования тетрады в символ цифры:

;Процедура преобразования числа (0-15) в шестнадцатеричную цифру ; вход : AL - число (0-15) ; выход: AL - шестнадцатеричная цифра ('0'-'F') to_hex_digit: add al,'0' ;Прибавляем символ '0' (код 0x30) cmp al,'9' ;Сравнение с символом '9' (код 0x39) jle thd_end ;Если получилось '0'-'9', то выход add al,7 ;Прибавляем ещё 7 для символов 'A'-'F' thd_end: ret

Если значение тетрады от 0 до 9, то достаточно только прибавить код символа ‘0’ (0x30). А если значение больше 9, то надо прибавить ещё 7, чтобы получилась буква ‘A’-‘F’. Теперь легко можно преобразовать байт в шестнадцатеричную строку, достаточно каждую из его тетрад заменить соответствующей цифрой:

;Процедура преобразования байта в строку в шестнадцатеричном виде ; AL - байт. ; DI - буфер для строки (2 символа). Значение регистра не сохраняется. byte_to_hex_str: push ax mov ah,al ;Сохранение значения AL в AH shr al,4 ;Выделение старшей тетрады call to_hex_digit ;Преобразование в шестнадцатеричную цифру mov [di],al ;Добавление символа в строку inc di ;Инкремент DI mov al,ah ;Восстановление AL and al,0Fh ;Выделение младшей тетрады call to_hex_digit ;Преобразование в шестнадцатеричную цифру mov [di],al ;Добавление символа в строку inc di ;Инкремент DI pop ax ret

Преобразование слова также не представляет трудности — сначала преобразуем старший байт, затем младший:

;Процедура преобразования слова в строку в шестнадцатеричном виде ; AX - слово ; DI - буфер для строки (4 символа). Значение регистра не сохраняется. word_to_hex_str: xchg ah,al ;Обмен AH и AL call byte_to_hex_str ;Преобразование старшего байта в строку xchg ah,al ;Обмен AH и AL call byte_to_hex_str ;Преобразование младшего байта в строку ret

Результат работы программы выглядит вот так:

Вывод чисел в десятичном виде

С десятичными числами немного сложнее. Для начала займёмся числами без знака. Чтобы преобразовать число в десятичную строку необходимо в цикле делить его на 10 (это основание системы счисления). Остатки от деления дают нам значения десятичных цифр. Первый остаток — младшая цифра, последний — старшая. Деление продолжается пока частное не равно нулю. Например, если есть число 125. Делим его на десять: получаем 12, 5 в остатке. Потом делим 12 на десять: получаем 1, 2 в остатке. Наконец, 1 делим на 10: получаем 0, 1 в остатке. Цифры числа, начиная с младшей: 5, 2, 1. Так как обычно десятичные числа пишут, начиная со старшей цифры, то необходимо переставить их наоборот. Я для этого использовал стек. В первом цикле производится деление, полученные остатки преобразуются в цифры и помещаются в стек. Во втором цикле символы извлекаются из стека (в обратном порядке) и помещаются в строку. Так как максимальное значение слова без знака 65536 (5 цифр), то в буфер записывается максимум 5 символов.

;Процедура преобразования слова в строку в десятичном виде (без знака) ; AX - слово ; DI - буфер для строки (5 символов). Значение регистра не сохраняется. word_to_udec_str: push ax push cx push dx push bx xor cx,cx ;Обнуление CX mov bx,10 ;В BX делитель (10 для десятичной системы) wtuds_lp1: ;Цикл получения остатков от деления xor dx,dx ;Обнуление старшей части двойного слова div bx ;Деление AX=(DX:AX)/BX, остаток в DX add dl,'0' ;Преобразование остатка в код символа push dx ;Сохранение в стеке inc cx ;Увеличение счетчика символов test ax,ax ;Проверка AX jnz wtuds_lp1 ;Переход к началу цикла, если частное не 0. wtuds_lp2: ;Цикл извлечения символов из стека pop dx ;Восстановление символа из стека mov [di],dl ;Сохранение символа в буфере inc di ;Инкремент адреса буфера loop wtuds_lp2 ;Команда цикла pop bx pop dx pop cx pop ax ret

Для вывода байта можно преобразовать его в слово и воспользоваться той же процедурой:

;Процедура преобразования байта в строку в десятичном виде (без знака) ; AL - байт. ; DI - буфер для строки (3 символа). Значение регистра не сохраняется. byte_to_udec_str: push ax xor ah,ah ;Преобразование байта в слово (без знака) call word_to_udec_str ;Вызов процедуры для слова без знака pop ax ret

Теперь разберёмся с числами со знаком. Сначала нужно проверить старший бит числа. Если число положительное, то его можно преобразовать также как число без знака. Если число отрицательное, то добавляем в строку символ ‘-‘, а затем инвертируем число и преобразуем как беззнаковое.

;Процедура преобразования слова в строку в десятичном виде (со знаком) ; AX - слово ; DI - буфер для строки (6 символов). Значение регистра не сохраняется. word_to_sdec_str: push ax test ax,ax ;Проверка знака AX jns wtsds_no_sign ;Если >= 0, преобразуем как беззнаковое mov byte[di],'-' ;Добавление знака в начало строки inc di ;Инкремент DI neg ax ;Изменение знака значения AX wtsds_no_sign: call word_to_udec_str ;Преобразование беззнакового значения pop ax ret ;Процедура преобразования байта в строку в десятичном виде (со знаком) ; AL - байт. ; DI - буфер для строки (4 символа). Значение регистра не сохраняется. byte_to_sdec_str: push ax movsx ax,al ;Преобразование байта в слово (со знаком) call word_to_sdec_str ;Вызов процедуры для слова со знаком pop ax ret

Результат работы программы выглядит вот так: Как вывести на консоль в десятичном виде очень большое число (> 32 бит) читайте здесь.

Вывод чисел в восьмеричном виде

Выводить числа в восьмеричном виде приходится достаточно редко, поэтому подробно описывать не буду. Можно либо делить число последовательно на 8, либо преобразовывать в цифры группы по 3 бита. Я использовал второй вариант.
Результат работы программы:

Вывод чисел в других системах счисления

Реализуется также, как вывод в десятичном виде — с помощью алгоритма последовательного деления на основание системы счисления. Например, если вам нужно вывести число в пятеричной системе счисления, делить надо на 5, а не на 10.

Упражнение

Напишите программу для вывода на консоль массива слов со знаком в десятичном виде (например, через запятую). Для вывода чисел можете воспользоваться моим примером или написать свою собственную процедуру. Результаты можете писать в комментариях или на форуме.

Предыдущий урок Список уроков Следующий урок

10.07.2020 в 13:40 #7219
Исходные коды программ целиком:
1. Вывод в двоичном виде:

; (c) xrnd [2010] [http://asmworld.ru/] ; printbin.asm - вывод чисел в двоичном виде use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov ax,1234h ;Число, которое будем выводить (1234h) mov cx,print_str ;Адрес процедуры print_str mov bx,print_endline ;Адрес процедуры print_endline mov di,s_byte call cx ;Вывод строки 'byte:' call print_byte_bin ;Вывод AL в двоичном виде call bx ;Вывод конца строки mov di,s_word call cx ;Вывод строки 'word:' call print_word_bin ;Вывод AX в двоичном виде call bx ;Вывод конца строки mov di,s_pak call cx ;Вывод строки 'Press any key. ' mov ah,8 ;Функция DOS 08h - ввод символа без эха int 21h mov ax,4C00h ;\ int 21h ;/ Завершение программы ;---------------------------------------------------------------------- ;Процедура вывода байта на консоль в двоичном виде ; AL - байт print_byte_bin: push di mov di,buffer ;DI = адрес буфера call byte_to_bin_str ;Преобразование байта в AL в строку mov byte[di],'$' ;Добавление символа конца строки sub di,8 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода слова на консоль в двоичном виде ; AX - слово print_word_bin: push di mov di,buffer ;DI = адрес буфера call word_to_bin_str ;Преобразование слова в AX в строку mov byte[di],'$' ;Добавление символа конца строки sub di,16 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода строки на консоль ; DI - адрес строки print_str: push ax mov ah,9 ;Функция DOS 09h - вывод строки xchg dx,di ;Обмен значениями DX и DI int 21h ;Обращение к функции DOS xchg dx,di ;Обмен значениями DX и DI pop ax ret ;---------------------------------------------------------------------- ;Процедура вывода конца строки (CR+LF) print_endline: push di mov di,endline ;DI = адрес строки с символами CR,LF call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура преобразования байта в строку в двоичном виде ; AL - байт. ; DI - буфер для строки (8 символов). Значение регистра не сохраняется. byte_to_bin_str: push cx ;Сохранение CX mov cx,8 ;Счётчик цикла btbs_lp: rol al,1 ;Циклический сдвиг AL влево на 1 бит jc btbs_1 ;Если выдвинутый бит = 1, то переход mov byte[di],'0' ;Добавление символа '0' в строку jmp btbs_end btbs_1: mov byte[di],'1' ;Добавление символа '1' в строку btbs_end: inc di ;Инкремент DI loop btbs_lp ;Команда цикла pop cx ;Восстановление CX ret ;Возврат из процедуры ;---------------------------------------------------------------------- ;Процедура преобразования слова в строку в двоичном виде ; AX - слово ; DI - буфер для строки (16 символов). Значение регистра не сохраняется. word_to_bin_str: xchg ah,al ;Обмен AH и AL call byte_to_bin_str ;Преобразование старшего байта в строку xchg ah,al ;Обмен AH и AL call byte_to_bin_str ;Преобразование младшего байта в строку ret ;--------------------------------------------------------------------- ; Данные s_byte db 'byte: $' s_word db 'word: $' s_pak db 'Press any key. $' endline db 13,10,'$' buffer rb 17

2. Вывод в восьмеричном виде:

; (c) xrnd [2010] [http://asmworld.ru/] ; printoct.asm - вывод чисел в восьмеричном виде use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov ax,0x89AB ;Число, которое будем выводить mov cx,print_str ;Адрес процедуры print_str mov bx,print_endline ;Адрес процедуры print_endline mov di,s_byte call cx ;Вывод строки 'byte:' call print_byte_oct ;Вывод AL в восьмеричном виде call bx ;Вывод конца строки mov di,s_word call cx ;Вывод строки 'word:' call print_word_oct ;Вывод AX в восьмеричном виде call bx ;Вывод конца строки mov di,s_pak call cx ;Вывод строки 'Press any key. ' mov ah,8 ;Функция DOS 08h - ввод символа без эха int 21h mov ax,4C00h ;\ int 21h ;/ Завершение программы ;---------------------------------------------------------------------- ;Процедура вывода байта на консоль в восьмеричном виде ; AL - байт print_byte_oct: push di mov di,buffer ;DI = адрес буфера call byte_to_oct_str ;Преобразование байта в AL в строку mov byte[di],'$' ;Добавление символа конца строки sub di,3 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода слова на консоль в восьмеричном виде ; AX - слово print_word_oct: push di mov di,buffer ;DI = адрес буфера call word_to_oct_str ;Преобразование слова в AX в строку mov byte[di],'$' ;Добавление символа конца строки sub di,6 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода строки на консоль ; DI - адрес строки print_str: push ax mov ah,9 ;Функция DOS 09h - вывод строки xchg dx,di ;Обмен значениями DX и DI int 21h ;Обращение к функции DOS xchg dx,di ;Обмен значениями DX и DI pop ax ret ;---------------------------------------------------------------------- ;Процедура вывода конца строки (CR+LF) print_endline: push di mov di,endline ;DI = адрес строки с символами CR,LF call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура преобразования байта в строку в восьмеричном виде ; AL - байт. ; DI - буфер для строки (3 символа). Значение регистра не сохраняется. byte_to_oct_str: push ax push cx mov ah,al ;Сохранение значения AL в AH mov cx,6 ;Счётчик сдвигов btos_lp: shr al,cl ;Сдвиг AL на CL бит вправо and al,7 ;Выделение очередной триады add al,'0' ;Преобразование в восьмеричную цифру mov [di],al ;Добавление символа в строку inc di ;Инкремент DI jcxz btos_lp_end ;Если CX = 0, то выход из цикла mov al,ah ;Восстановление AL sub cx,3 ;Уменьшение счетчика сдвигов на 3 jmp btos_lp btos_lp_end: pop cx ;Восстановление регистров pop ax ret ;---------------------------------------------------------------------- ;Процедура преобразования слова в строку в восьмеричном виде ; AX - слово ; DI - буфер для строки (6 символов). Значение регистра не сохраняется. word_to_oct_str: push ax push dx push cx mov dx,ax ;Сохранение значения AX в DX mov cx,15 ;Счётчик сдвигов wtos_lp: shr ax,cl ;Сдвиг AX на CL бит вправо and ax,7 ;Выделение очередной триады add al,'0' ;Преобразование в восьмеричную цифру mov [di],al ;Добавление символа в строку inc di ;Инкремент DI jcxz wtos_lp_end ;Если CX = 0, то выход из цикла mov ax,dx ;Восстановление AX sub cx,3 ;Уменьшение счетчика сдвигов на 3 jmp wtos_lp wtos_lp_end: pop cx ;Восстановление регистров pop dx pop ax ret ;--------------------------------------------------------------------- ; Данные s_byte db 'byte: $' s_word db 'word: $' s_pak db 'Press any key. $' endline db 13,10,'$' buffer rb 7

3. Вывод в шестнадцатеричном виде:

; (c) xrnd [2010] [http://asmworld.ru/] ; printhex.asm - вывод чисел в шестнадцатеричном виде use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov ax,0xA15F ;Число, которое будем выводить mov cx,print_str ;Адрес процедуры print_str mov bx,print_endline ;Адрес процедуры print_endline mov di,s_byte call cx ;Вывод строки 'byte:' call print_byte_hex ;Вывод AL в шестнадцатеричном виде call bx ;Вывод конца строки mov di,s_word call cx ;Вывод строки 'word:' call print_word_hex ;Вывод AX в шестнадцатеричном виде call bx ;Вывод конца строки mov di,s_pak call cx ;Вывод строки 'Press any key. ' mov ah,8 ;Функция DOS 08h - ввод символа без эха int 21h mov ax,4C00h ;\ int 21h ;/ Завершение программы ;---------------------------------------------------------------------- ;Процедура вывода байта на консоль в шестнадцатеричном виде ; AL - байт print_byte_hex: push di mov di,buffer ;DI = адрес буфера call byte_to_hex_str ;Преобразование байта в AL в строку mov byte[di],'$' ;Добавление символа конца строки sub di,2 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода слова на консоль в шестнадцатеричном виде ; AX - слово print_word_hex: push di mov di,buffer ;DI = адрес буфера call word_to_hex_str ;Преобразование слова в AX в строку mov byte[di],'$' ;Добавление символа конца строки sub di,4 ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода строки на консоль ; DI - адрес строки print_str: push ax mov ah,9 ;Функция DOS 09h - вывод строки xchg dx,di ;Обмен значениями DX и DI int 21h ;Обращение к функции DOS xchg dx,di ;Обмен значениями DX и DI pop ax ret ;---------------------------------------------------------------------- ;Процедура вывода конца строки (CR+LF) print_endline: push di mov di,endline ;DI = адрес строки с символами CR,LF call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура преобразования числа (0-15) в шестнадцатеричную цифру ; вход : AL - число (0-15) ; выход: AL - шестнадцатеричная цифра ('0'-'F') to_hex_digit: add al,'0' ;Прибавляем символ '0' (код 0x30) cmp al,'9' ;Сравнение с символом '9' (код 0x39) jle thd_end ;Если получилось '0'-'9', то выход add al,7 ;Прибавляем ещё 7 для символов 'A'-'F' thd_end: ret ;---------------------------------------------------------------------- ;Процедура преобразования байта в строку в шестнадцатеричном виде ; AL - байт. ; DI - буфер для строки (2 символа). Значение регистра не сохраняется. byte_to_hex_str: push ax mov ah,al ;Сохранение значения AL в AH shr al,4 ;Выделение старшей тетрады call to_hex_digit ;Преобразование в шестнадцатеричную цифру mov [di],al ;Добавление символа в строку inc di ;Инкремент DI mov al,ah ;Восстановление AL and al,0Fh ;Выделение младшей тетрады call to_hex_digit ;Преобразование в шестнадцатеричную цифру mov [di],al ;Добавление символа в строку inc di ;Инкремент DI pop ax ret ;---------------------------------------------------------------------- ;Процедура преобразования слова в строку в шестнадцатеричном виде ; AX - слово ; DI - буфер для строки (4 символа). Значение регистра не сохраняется. word_to_hex_str: xchg ah,al ;Обмен AH и AL call byte_to_hex_str ;Преобразование старшего байта в строку xchg ah,al ;Обмен AH и AL call byte_to_hex_str ;Преобразование младшего байта в строку ret ;--------------------------------------------------------------------- ; Данные s_byte db 'byte: $' s_word db 'word: $' s_pak db 'Press any key. $' endline db 13,10,'$' buffer rb 5

4. Вывод в десятичном виде:

; (c) xrnd [2010] [http://asmworld.ru/] ; printdec.asm - вывод чисел в десятичном виде (со знаком и без знака) use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov ax,0xA83D ;Число, которое будем выводить mov cx,print_str ;Адрес процедуры print_str mov bx,print_endline ;Адрес процедуры print_endline mov di,s_ubyte call cx ;Вывод строки 'unsigned byte:' call print_byte_udec ;Вывод AL в десятичном виде (без знака) call bx ;Вывод конца строки mov di,s_uword call cx ;Вывод строки 'unsigned word:' call print_word_udec ;Вывод AX в десятичном виде (без знака) call bx ;Вывод конца строки mov di,s_sbyte call cx ;Вывод строки 'signed byte :' call print_byte_sdec ;Вывод AL в десятичном виде (со знаком) call bx ;Вывод конца строки mov di,s_sword call cx ;Вывод строки 'signed word :' call print_word_sdec ;Вывод AX в десятичном виде (со знаком) call bx ;Вывод конца строки mov di,s_pak call cx ;Вывод строки 'Press any key. ' mov ah,8 ;Функция DOS 08h - ввод символа без эха int 21h mov ax,4C00h ;\ int 21h ;/ Завершение программы ;---------------------------------------------------------------------- ;Процедура вывода байта на консоль в десятичном виде (без знака) ; AL - байт print_byte_udec: push di mov di,buffer ;DI = адрес буфера push di ;Сохранение DI в стеке call byte_to_udec_str ;Преобразование байта в AL в строку mov byte[di],'$' ;Добавление символа конца строки pop di ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода слова на консоль в десятичном виде (без знака) ; AX - слово print_word_udec: push di mov di,buffer ;DI = адрес буфера push di ;Сохранение DI в стеке call word_to_udec_str ;Преобразование слова в AX в строку mov byte[di],'$' ;Добавление символа конца строки pop di ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода байта на консоль в десятичном виде (со знаком) ; AL - байт print_byte_sdec: push di mov di,buffer ;DI = адрес буфера push di ;Сохранение DI в стеке call byte_to_sdec_str ;Преобразование байта в AL в строку mov byte[di],'$' ;Добавление символа конца строки pop di ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода слова на консоль в десятичном виде (со знаком) ; AX - слово print_word_sdec: push di mov di,buffer ;DI = адрес буфера push di ;Сохранение DI в стеке call word_to_sdec_str ;Преобразование слова в AX в строку mov byte[di],'$' ;Добавление символа конца строки pop di ;DI = адрес начала строки call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура вывода строки на консоль ; DI - адрес строки print_str: push ax mov ah,9 ;Функция DOS 09h - вывод строки xchg dx,di ;Обмен значениями DX и DI int 21h ;Обращение к функции DOS xchg dx,di ;Обмен значениями DX и DI pop ax ret ;---------------------------------------------------------------------- ;Процедура вывода конца строки (CR+LF) print_endline: push di mov di,endline ;DI = адрес строки с символами CR,LF call print_str ;Вывод строки на консоль pop di ret ;---------------------------------------------------------------------- ;Процедура преобразования байта в строку в десятичном виде (без знака) ; AL - байт. ; DI - буфер для строки (3 символа). Значение регистра не сохраняется. byte_to_udec_str: push ax xor ah,ah ;Преобразование байта в слово (без знака) call word_to_udec_str ;Вызов процедуры для слова без знака pop ax ret ;---------------------------------------------------------------------- ;Процедура преобразования слова в строку в десятичном виде (без знака) ; AX - слово ; DI - буфер для строки (5 символов). Значение регистра не сохраняется. word_to_udec_str: push ax push cx push dx push bx xor cx,cx ;Обнуление CX mov bx,10 ;В BX делитель (10 для десятичной системы) wtuds_lp1: ;Цикл получения остатков от деления xor dx,dx ;Обнуление старшей части двойного слова div bx ;Деление AX=(DX:AX)/BX, остаток в DX add dl,'0' ;Преобразование остатка в код символа push dx ;Сохранение в стеке inc cx ;Увеличение счетчика символов test ax,ax ;Проверка AX jnz wtuds_lp1 ;Переход к началу цикла, если частное не 0. wtuds_lp2: ;Цикл извлечения символов из стека pop dx ;Восстановление символа из стека mov [di],dl ;Сохранение символа в буфере inc di ;Инкремент адреса буфера loop wtuds_lp2 ;Команда цикла pop bx pop dx pop cx pop ax ret ;---------------------------------------------------------------------- ;Процедура преобразования байта в строку в десятичном виде (со знаком) ; AL - байт. ; DI - буфер для строки (4 символа). Значение регистра не сохраняется. byte_to_sdec_str: push ax movsx ax,al ;Преобразование байта в слово (со знаком) call word_to_sdec_str ;Вызов процедуры для слова со знаком pop ax ret ;---------------------------------------------------------------------- ;Процедура преобразования слова в строку в десятичном виде (со знаком) ; AX - слово ; DI - буфер для строки (6 символов). Значение регистра не сохраняется. word_to_sdec_str: push ax test ax,ax ;Проверка знака AX jns wtsds_no_sign ;Если >= 0, преобразуем как беззнаковое mov byte[di],'-' ;Добавление знака в начало строки inc di ;Инкремент DI neg ax ;Изменение знака значения AX wtsds_no_sign: call word_to_udec_str ;Преобразование беззнакового значения pop ax ret ;--------------------------------------------------------------------- ; Данные s_ubyte db 'unsigned byte: $' s_uword db 'unsigned word: $' s_sbyte db 'signed byte : $' s_sword db 'signed word : $' s_pak db 'Press any key. $' endline db 13,10,'$' buffer rb 7

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *