|
Основы программирования на ассемблере |
| Содержание | <<< | >>> |
Флаги нуля, знака
и переполнения
|
0ABD:0100 B402 0ABD:0102 B22A 0ABD:0104 B109 0ABD:0106 CD21 0ABD:0108 80E901 0ABD:010B 75F9 0ABD:010D CD20 |
![]() |
MOV AH,02 загружаем функцию печати символа MOV DL,2A загружаем код символа "*" MOV CL,09 устанавливаем счетчик повторений INT 21 печатаем символ SUB CL,01 уменьшаем CL на 1 JNZ 0106 если ZF = NZ, то переход на адрес 106 INT 20 |
Используя трассировку программы, проанализируйте действия инструкции
JNZ.
Задачи:
| Символ | ASCII код |
| 0 | 30h |
| 1 | 31h |
| 2 | 32h |
| 3 | 33h |
| 4 | 34h |
| 5 | 35h |
| 6 | 36h |
| 7 | 37h |
| 8 | 38h |
| 9 | 39h |
| : | 3Ah |
| ; | 3Bh |
| < | 3Ch |
| = | 3Dh |
| > | 3Eh |
| ? | 3Fh |
| @ | 40h |
| A | 41h |
| B | 42h |
| C | 43h |
| D | 44h |
| E | 45h |
| F | 46h |
Ранее мы рассмотрели алгоритм вывода на экран цифр 0 и 1, где код символа формировался сложением соответствующей цифры с числом 30h. Аналогичный метод можно применить для вывода на экран шестнадцатеричных чисел.
Из таблицы ASCII кодов видно, что коды символов "0" ... "9" можно получить
сложением 30h с соответствующим числом:
30h + 9h = 39h (код символа "9").
Коды символов "A" ... "F" формируются аналогично,
только вместо числа 30h используется число 37h:
37h + Dh = 44h (код символа "D").
Для вывода на экран шестнадцатеричных чисел, нам потребуются две новые инструкции:
0ABD:0100 B30E 0ABD:0102 B402 0ABD:0104 88DA 0ABD:0106 80C230 0ABD:0109 80FA3A 0ABD:010C 7C03 0ABD:010E 80C207 0ABD:0111 CD21 0ABD:0113 CD20 |
|
MOV BL,0E исходное число MOV AH,02 загружаем функцию печати символа MOV DL,BL копируем исходное число в DL ADD DL,30 формируем код символа CMP DL,3A сравниваем число из DL и 3Ah JL 0111 если DL < 3A, то переход на адрес 111 ADD DL,07 корректируем код для чисел A...F INT 21 печатаем символ INT 20 |
Загружая в регистр BL числа от 0 до F, выполните трассировку программы. Посмотрите, как изменяет флаги инструкция CMP. Проанализируйте действия инструкции JL.
Изменим программу так, чтобы она печатала любые числа от 0 до FFh. Для этого нам надо научиться выделять старшую и младшую цифры двузначного шестнадцатеричного числа.
Каждая цифра шестнадцатеричного числа занимает четыре бита. Для выделения четырех бит старшей цифры мы используем инструкцию SHR:
Исходное число загружаем в регистр DL.
Все восемь бит числа сдвигаем вправо,
через флаг переноса.
Число, после сдвига на четыре бита вправо:
(в освободившиеся ячейки регистра DL загружаются нули)
Программная реализация сдвига состоит из двух строк:
MOV CL,4 сдвиг на 4 бита SHR DL,CL число в регистре DL сдвигается вправо на 4 битаК сожалению Debug не позволяет указывать шаг сдвига непосредственно в инструкции, например: SHR DL,4 или RCL DL,4. Этот формат мы используем позже, при написании компилируемых ассемблерных программ.
0ABD:0100 B3B9 MOV BL,B9 загружаем исходное число 0ABD:0102 88DA MOV DL,BL копируем исходное число в DL 0ABD:0104 B402 MOV AH,02 загружаем функцию печати символа 0ABD:0106 B104 MOV CL,04 загружаем шаг сдвига 0ABD:0108 D2EA SHR DL,CL сдвигаем число в DL на CL бит вправо 0ABD:010A 80C230 ADD DL,30 формируем код символа 0ABD:010D 80FA3A CMP DL,3A определяем диапазон символа 0ABD:0110 7C03 JL 0115 если диапазон "0"..."9", то переход 0ABD:0112 80C207 ADD DL,07 иначе, корректируем код 0ABD:0115 CD21 INT 21 печатаем символ 0ABD:0117 CD20 INT 20Регистр BL не принимает участия в программе, его задача - сохранить копию числа для вывода на экран младшей цифры.
Выполните программу c разными исходными числами. Убедитесь, что на экран выводится старшая цифра шестнадцатеричного числа.
Для выделения четырех бит младшей цифры двузначного шестнадцатеричного
числа, нужно обнулить четыре бита старшей цифры. Для обнуления заданной
последовательности бит, мы используем инструкцию AND (логическое умножение
двух чисел).
Рассмотрим все варианты логического умножения чисел 1 и 0:
0 AND 1 = 0 0 AND 0 = 0 1 AND 0 = 0 1 AND 1 = 1Аналогично выглядит логическое умножение восьмиразрядных двоичных чисел:
10110101 10110110 AND 01110110 AND 00100101 00110111 00100100Логическое умножение байта на маску 0Fh, позволяет обнулить старшую половину байта:
10111001 B9h AND 00001111 ? AND 0Fh 00001001 09hИспользуем это свойство для вывода на экран младшей цифры шестнадцатеричного числа:
0ABD:0100 B3B9 MOV BL,B9 загружаем исходное число 0ABD:0102 88DA MOV DL,BL копируем исходное число в DL 0ABD:0104 B402 MOV AH,02 загружаем функцию печати символа 0ABD:0106 80E20F AND DL,0F обнуляем старшую половину байта 0ABD:0109 80C230 ADD DL,30 формируем код символа 0ABD:010C 80FA3A CMP DL,3A определяем диапазон символа 0ABD:010F 7C03 JL 0114 если диапазон "0"..."9", то переход 0ABD:0111 80C207 ADD DL,07 иначе, корректируем код 0ABD:0114 CD21 INT 21 печатаем символ 0ABD:0116 CD20 INT 20Выполните программу c разными исходными числами. Убедитесь, что на экран выводится младшая цифра шестнадцатеричного числа.
0ABD:0100 B402 MOV AH,02 0ABD:0102 88DA MOV DL,BL 0ABD:0104 B104 MOV CL,04 0ABD:0106 D2EA SHR DL,CL 0ABD:0108 80C230 ADD DL,30 0ABD:010B 80FA3A CMP DL,3A 0ABD:010E 7C03 JL 0113 0ABD:0110 80C207 ADD DL,07 0ABD:0113 CD21 INT 21 0ABD:0115 88DA MOV DL,BL 0ABD:0117 80E20F AND DL,0F 0ABD:011A 80C230 ADD DL,30 0ABD:011D 80FA3A CMP DL,3A 0ABD:0120 7C03 JL 0125 0ABD:0122 80C207 ADD DL,07 0ABD:0125 CD21 INT 21 0ABD:0127 CD20 INT 20В приведенном листинге нет загрузки исходного числа в регистр BL. Это делает программу более универсальной. Для ввода чисел в регистр используйте команду "R".
| Содержание | <<< | >>> |