5.4. Преобразование и вывод данных

Для вывода байта в шестнадцатеричном виде определим таблицу

table  db    ‘0123456789ABCDEF’ в которой значение шестнадцатеричной цифры будет равно смещению относительно начала таблицы символа, служащего ASCII – кодом этого значения. Например код ‘5’ находится по адресу table1+5, код ‘E’ находится по адресу table1+0Eh, и т.д.

Воспользуемся следующей командой

xlat

без операндов, операнды которой задаются неявно:

· bx — является указателем на начала массива символов,

· al — содержит число, которое служит смещением (индексом) байта, возвращаемого в регистр al.

Для нашей таблицы table1 после команд

lea   bx, table1

mov   al,5

xlat

в регистре al будет находиться символ ‘5’. Подпрограмма будет выводить содержимое байта следующим образом: берется старшая тетрада байта и выводится соответствующий ей символ. Потом выводится символ, соответствующий младшей тетраде.

hex    proc               ;вывод dl в шестнадцатеричном виде

       push  dx

       lea   bx,table1

       mov   al,dl

       shr   al,4

       xlat

       mov   dl,al        ;вывод

       mov   ah,2         ;старшей

       int   21h          ;цифры

       pop   ax

      and   al,00001111b

       xlat

       mov   dl,al        ;вывод

       mov   ah,2         ;младшей

       int   21h          ;цифры

       ret

table  db    ‘0123456789ABCDEF’

hex    endp

Напишем теперь подпрограммы вывода содержимого слова в шестнадцатеричном виде. Воспользуемся подпрограммой hex, с помощью которой будем выводить сначала старший, а затем младший байты. Наши подпрограммы будут подсоединяться при сборке:

< 1 > title     mylib.obj

< 2 > subr     segment

< 3 > public    display, kbin, hex, hexw, crlf

< 4 > assume    cs:subr, ds:subr

< 5 > ;——подпрограммы———————

< 6 > display  proc

< 7 > mov       ah,2

< 8 > int       21h

< 9 > ret

< 10 > display  endp

< 11 >

< 12 > kbin     proc        ;ввод символа

< 13 > mov       ah,1       ;в регистр al

< 14 > int       21h

< 15 > ret

< 16 > kbin     endp

< 17 >

< 18 > hex      proc        ;вывод dl в 16-ном виде

< 19 > mov       ax,subr    ;инициализация ds

< 20 > mov       ds,ax      ;на сегмент, содержащий table1

< 21 > push      dx

< 22 > lea       bx,table1

< 23 > mov       ax,0

< 24 > mov       al,dl

< 25 > shr       al,4

< 26 > xlat                 ;преобразование

< 27 > mov       dl,al      ;ASCII-код цифры

< 28 > call      display

< 29 > pop       ax         ;бывшее содержимое dx

< 30 > and       al,00001111b    ;младший полубайт

< 31 > xlat

< 32 > mov       dl,al

< 33 > call      display

< 34 > ret

< 35 > table1   db    ‘0123456789ABCDEF’

< 36 > hex      endp

< 37 >

< 38 > hexw     proc        ;вывод в 16-ном виде

< 39 > mov       di,dx      ;сохранить dx

< 40 > mov       dl,dh      ;вывод старшего байта

< 41 > call      hex

< 42 > mov       dx,di      ;восстановить dx

< 43 > call      hex        ;вывод dl

< 44 > mov       dl,’ ‘     ;пробел

< 45 > call      display

< 46 > ret

< 47 > hexw     endp

< 48 >

< 49 > crlf     proc        ;вывод

< 50 > mov       dl,10      ;перевода

< 51 > call      display    ;строки и

< 52 > mov       dl,13      ;возврата

< 53 > call      display    ;каретки

< 54 > ret

< 55 > crlf     endp

subr  ends

< 1 >

< 2 > end

Команда xlat обращается к таблице, имеющей адрес ds:bx, поэтому в подпрограмме hex регистр ds инициализируется. Объектный модуль mylib.obj получается после компиляции данного текста mylib.asm. Если программа выводит некоторое слово с помощью hexw, то эта программа, после компиляции, собирается командой

     tlink  mylib + имя

в результате которой будет создан загрузочный модуль имя.exe.

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

div    bx ; ax = (dx:ax)/bx

записывающей в ax частное от деления регистровой пары (dx:ax), a в регистр dx – остаток. Все числа рассматриваются как беззнаковые. Поскольку наибольшее беззнаковое число равно 65535, будем выводить пять десятичных разрядов числа. Первая цифра будет равна целой части частного от деления этого числа на 10000. Вторая получается делением полученного остатка на 1000. Снова получим остаток, который надо поделить на 100, и т.д. Например, если число x = 1234, то получим цифры ai следующим образом:

          a1 = 01234 / 10000 = 0, остаток = 1234;

          a2 = 1234 / 1000 = 1, остаток = 234;

          a3 = 234 / 100 = 2, остаток = 34;

          a4 = 34 / 10 = 3, остаток = 4;

          a5 = 4.

Подпрограмма:

bintodec    proc     ;вывод ax в десятичном виде

      mov   bx,10000 ;вывод ax/bx

      call  show     ;остаток в ax

      mov   bx,1000

      call  show

      mov   bx,100

      call  show

      mov   bx,10

      call  show

      add   al,’0′   ;вывод последней

      mov   dl,al    ;цифры

      call  display

      call  crlf     ;переход на новую строку

      ret

bintodec    endp

Подпрограмма show делит ax на bx и остаток возвращает в ax:

show  proc

      mov   dx,0

      div   bx

      mov   di,dx

      add   al,’0′

      mov   dl,al

      call  display

      mov   ax,di

      ret

show  endp

Аналогичным образом составляется подпрограмма вывода числа в восьмеричном виде (используется та же подпрограмма show):

bintooct    proc        ;вывод ax в восьмеричном виде

      mov   bx,100000o

      call  show

      mov   bx,10000o

      call  show

      mov   bx,1000o

      call  show

      mov   bx,100o

      call  show

      mov   bx,10o

      call  show

      add   al,’0′

      mov   al,dl

      call  display

      call  crlf

      ret

bintooct    endp