Вывод на экран двоичных чисел

From AsIsWiki
Revision as of 12:00, 4 April 2015 by Alex (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Форум

Назад | Оглавление | Дальше


Contents

Введение

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


Циклический сдвиг и флаг переноса

Мы уже знаем, что при сложении некоторых чисел, в пятом разряде результата появляется единица, например:

FFFFh + 1 = 10000h

Микропроцессор хранит эту единицу в специальной ячейке, называемой флагом переноса - CF (Carry Flag).

Посмотрим, как Debug отображает значение флага CF. По адресу 100h запишите инструкцию ADD AX,BX, и загрузите регистры AX = FFFFh, BX = 1h:

AX=FFFF  BX=0001  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0ABD  ES=0ABD  SS=0ABD  CS=0ABD  IP=0100   NV UP EI PL NZ NA PO NC
0ABD:0100 01D8          ADD     AX,BX

Жирным шрифтом выделены значения различных флагов микропроцессора. В этой строке нас интересует флаг NC (No Carry - нет переноса). Выполните трассировку инструкции, и вновь просмотрите регистры.

Состояние флага изменилось CY (Carry - перенос). В результате сложения чисел произошел перенос единицы в пятый разряд, при этом CF принял значение CY.

Если операция проходит без переноса в пятый разряд, то флаг переноса принимает значение NC. Например, выполните сложение 2 + 3, и убедитесь, что CF = NC.

Для вывода на экран двоичных чисел, мы используем инструкцию RCL (Rotate Carry Left), которая сдвигает число на один бит влево через флаг переноса.

В исходном состоянии BL = B7h (10110111b). На рисунке показано состояние регистра BL и флага CF после сдвига числа на один бит влево:

CF BL
0 10110111 B7h
1 01101110 6Eh
0 11011101 DDh
1 10111010 BAh
1 01110101 75h
0 11101011 EBh
1 11010110 D6h
1 10101101 ADh
1 01011011 5Bh
0 10110111 B7h

Image23.gif

После прохождения флага переноса, бит возвращается в младший разряд регистра BL. Через девять циклических сдвигов число полностью вернется в регистр BL:

  1. Загрузите в регистр BL число B7h
  2. По адресу 100h запишите инструкцию RCL BL,1
  3. Проверьте стартовый адрес IP = 100h
  4. Выполните инструкцию 9 раз (возвращая IP = 100h)
  5. Убедитесь, что число прошло все стадии сдвига, и вернулось в исходное состояние.

Инструкцию RCL можно использовать и с другими регистрами. Например: RCL DL,1 будет сдвигать байт в регистре DL на один бит влево, через флаг переноса.

Далее мы научимся преобразовывать значение флага переноса, в символ "1" или "0" для последующей печати.


Сложение с использованием флага переноса

Для вывода символа на экран мы использовали функцию 02h прерывания INT 21h. При этом, в регистре DL мы указывали ASCII код символа. Вывод на экран двоичного числа сводится к последовательной печати символов "0" и "1". Эти символы имеют коды: "0" - 30h, "1" - 31h

При циклическом сдвиге RCL все биты числа (от старшего до младшего) проходят через флаг переноса. Выполняя сложение CF + 30h мы получим код символа "0" или "1" (в зависимости от значения CF):

CF = 0:   30h + CF = 30h (код символа "0")
CF = 1:   30h + CF = 31h (код символа "1")

Инструкция ADC (Add with Carry) выполняет сложение двух чисел, и добавляет к сумме бит CF. Например, для суммы DL + 30h + CF, мнемокод инструкции выглядит так:

ADC DL,30  =>  DL = DL + 30h + CF

Результат сложения попадает в регистр DL. Если до выполнения инструкции регистр DL = 0, то после суммирования в DL появится код символа "0" или "1" (30h или 31h).

Обобщив все идеи, мы получаем алгоритм вывода на экран старшего бита числа:

  1. сдвигаем число влево на один бит;
  2. преобразуем флаг переноса в код символа;
  3. выводим символ на экран.

Если этот алгоритм повторить 8 раз (для байта) или 16 раз (для слова), то на экране появится цепочка нулей и единиц, соответствующая двоичному представлению заданного числа.


Организация цикла

Рассмотрим программу вывода на экран старшего бита числа B7h:

0ABD:0100 B7B7          MOV     BH,B7    загружаем исходное число
0ABD:0102 B402          MOV     AH,02    загружаем функцию печати символа
0ABD:0104 B200          MOV     DL,00    обнуляем регистр DL
0ABD:0106 D0D7          RCL     BH,1     сдвигаем число на бит влево
0ABD:0108 80D230        ADC     DL,30    выполняем сложение DL + 30h + CF
0ABD:010B CD21          INT     21       выводим на экран символ (код в DL)
0ABD:010D CD20          INT     20       завершаем работу

Перед сложением необходимо обнулять DL, иначе код символа будет сформирован неверно. После RCL сдвига, бит попадает в CF и добавляется в сумму:

DL = DL + 30h + CF

В результате сложения, регистр DL получает код символа "1" или "0".

Для вывода остальных битов числа B7h, надо повторить выделенный фрагмент еще семь раз. Организацию циклических повторов мы доверим инструкции LOOP:

0ABD:0100 B7B7       	MOV     BH,B7
0ABD:0102 B402       	MOV     AH,02
0ABD:0104 B90800     	MOV     CX,0008  загружаем число повторений
0ABD:0107 B200    ┌─>	MOV     DL,00    обнуляем регистр DL
0ABD:0109 D0D7RCL     BH,1     сдвигаем число на бит влево
0ABD:010B 80D230ADC     DL,30    выполняем сложение DL + 30h + CF
0ABD:010E CD21INT     21       выводим на экран символ
0ABD:0110 E2F5    └─	LOOP    0107     если CX > 0, то возврат на адрес 107
0ABD:0112 CD20       	INT     20

Инструкция LOOP работает в паре с регистром CX, и выполняет три действия:

  1. проверяет число в регистре CX;
  2. если CX > 0, то LOOP уменьшает CX на 1 и возвращает управление на 107 адрес;
  3. если CX = 0, то LOOP передает управление следующей инструкции (INT 20h).

Почему в качестве счетчика повторений выбран регистр CX? Буква "C" в названии регистра CX указывает на его функцию: Count (счетчик). Поэтому CX в основном используется при организации циклов.

Введите программу в память. Проверьте IP и выполните команду "G":

-g
10110111
Program terminated normally

Испытайте программу с другим числом, для этого измените значение регистра BH:

-a 100
0ABD:0100 MOV BH,FE
0ABD:0102 <Enter>

Число FEh можно записать иначе:

-e 101
0ABD:0101  B7.EF

Проверьте действие программы со следующими числами:

AFh   6Dh   FFh   7Ch   8Bh   C6h

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

Основная задача Debug - это пошаговая отладка программ. Поэтому, в качестве следующего упражнения выполните трассировку программы, анализируя:

  • содержимое регистров BH, DL, CX;
  • состояние флага переноса CF;
  • текущую мнемоническую инструкцию.

Для выполнения прерываний (INT 21h, INT 20h) используйте команду "P" (Proceed - переход). В отличие от команды "G", в команде "P" не надо указывать адрес остановки.

Задачи:

  1. Измените программу так, чтобы она добавляла символ "b" в конец двоичной записи.
  2. Напишите программу для вывода на экран двоичного слова из регистра BX.



Форум

Назад | Оглавление | Дальше

Personal tools
Namespaces

Variants
Actions
Navigation
Tools