Вывод первый. Для
цифр 0...9
отличается от со-
ответствующего двоичного представления на
0000, или 30h. Поэтому для пре-
образования кода символа
цифры в соответствующее двоич-
ное число есть два пути:
выполнить двоичное вычитание:
-
Ж обнулить старшую тетраду
с символом шестнадцатеричной цифры
в
Видно, что с
цифрами в диапазоне от 0 до 9 все просто.
Что касается шестнадцатеричных цифр а,
с, d, e, f, то здесь ситуация несколько
сложнее. Алгоритм должен распознавать эти символы и производить дополнитель-
ные действия при их преобразовании в соответствующее двоичное число. Внима-
тельный взгляд на символы шестнадцатеричных цифр и соответствующие им
двоичные представления (см. табл.
говорит о том, для преобразования уже не-
достаточно простого вычитания или обнуления старшей тетрады. Анализ таблицы
ASCII показывает, что символы прописных букв шестнадцатеричных цифр отли-
чаются от своего двоичного эквивалента на величину 37h. Соответствующие строч-
ные буквы шестнадцатеричных цифр отличаются от своего двоичного эквивален-
та на
67h.
Отсюда следует вывод второй. Алгоритм преобразования должен различать
Прописные и строчные буквенные символы шестнадцатеричных цифр и корректи-
ровать значение ASCII-кода на величину 37h или 67h.
Обратите внимание на то, что после записи значения шестнадцатеричной циф-
ры следует символ
Как упоминалось в главе 4, это сделано для того, чтобы
транслятор мог различить в программе одинаковые по форме записи десятичные
и
числа.
В листинге
приведен исходный текст программы, которая решает задачу
преобразования двузначного
числа в символьном виде в дво-
ичное представление.
Листинг
Пример программы на ассемблере
<1>
<2>
преобразования двузначного шестнадцатеричного числа
<3> ;в символьном виде в двоичное
исходное
число из двух цифр,
<5> ;вводится с клавиатуры.
<б>
результат преобразования помещается в регистр
<9> data segment para public "data" ;сегмент данных
<10> message db "Введите две шестнадцатеричные
<11> data ends
<12> stk segment stack
<13> db 256 dup
<14> stk ends
<15> code segment para public "code"
<16> main proc
сегмент стека
начало сегмента кода
начало процедуры main
<17> assume
<18> mov
;адрес сегмента данных в
Глава 6. Первая программа
Листинг
(продолжение)
<20>
<22>
<23>
<24>
<25>
<2б>
<27>
<28>
<29>
<30>
;ax в
raov
message
int
ax
xor
mov
int
mov
sub
cmp dl
30h
9h
sub
Ml
dl, 7h
Ml:
<32>
<33>
<34>
<35>
<36>
<37>
<38>
<39>
mov
int
sub
cmp al
jle M2
sub al
cl,4h
9h
,7h
<42>
<43>
<44>
<45>
add
mov
int 21h
main endp
code ends
end main
очистить регистр ах
в регистр ah
генерация прерывания с номером
содержимое регистра al в регистр dl
вычитание: (dl)=(dl)-30h
сравнить (dl) с
перейти на метку Ml, если dl<9h или dl=9h
вычитание:
определение метки Ml
пересылка 4h в регистр
сдвиг содержимого
4 разряда влево
вызов прерывания с номером 21h
вычитание:
сравнить (al) с 9h
перейти на метку М2, если al<9h или
вычитание:
определение метки М2
сложение:
пересылка
в регистр ах
вызов прерывания с номером
конец процедуры m a i n
конец сегмента кода
конец программы
входа main
В предыдущих главах говорилось, что процессор
шесть
адресно-независимых областей памяти: сегмент
сегмент данных, сегмент стека
и три дополнительных сегмента данных. Наша программа использует только пер-
вые три из них.
Строки
определяют сегмент данных. В строке 10 описана текстовая стро-
ка с сообщением «Введите две
цифры».
Строки 12-14 описывают сегмент стека, который является просто областью
памяти длиной 256 байт, инициализированной символами
Отличие сегмен-
та стека от сегментов других типов состоит в использовании и адресации памяти.
В отличие от сегмента данных (наличие которого необязательно, если программа
не работает с данными), сегмент стека желательно определять всегда.
Строки 15-44 содержат сегмент кода. В этом сегменте в строках 16-43 опреде-
лена одна процедура main.
Строка 17 содержит директиву ассемблера, которая связывает сегментные ре-
гистры с именами сегментов.
Строки 18-19 выполняют инициализацию сегментного регистра DS.
Строки 20-22 выводят на экран сообщение message:
Введите две шестнадцатеричные цифры
Строка 23 подготавливает регистр АХ к работе, обнуляя его. Содержимое АХ после
этой операции следующее:
ах = 0000 0000 0000 0000
Строки 24-25 обращаются к средствам операционной системы для ввода сим-
вола с клавиатуры. Введенный символ операционная система помещает в регистр
AL. К примеру, пусть в ответ на сообщение с клавиатуры были введены две шест-
надцатеричные цифры:
5С
Пример простой программы
В результате после отработки команды в строке 25 появится один символ
в ASCII-коде — 5, и состояние регистра АХ станет таким:
ах = 0000 0001 0011 0101
Строка 26 пересылает содержимое AL в регистр DL. Это делается для того, чтобы
освободить AL для ввода второй цифры. Содержимое регистра DX после этой пере-
сылки следующее:
dx = 0000
0011 0101
Строка 27 преобразует символьную цифру 5 в ее двоичный эквивалент пу-
тем вычитания 30h, в результате чего в регистре DL будет двоичное значение
числа 5:
dx = 0000 0000 0000 0101
В строках 28-29 выясняется, нужно ли корректировать двоичное значение в DL.
Если оно лежит в диапазоне 0...9, то в DL находится правильный двоичный эквива-
лент введенного символа
цифры. Если значение в DL больше 9,
то введенная цифра является одним из символов А, В, С, D, E, F (строчные буквы
для экономии места обрабатывать не будем). В первом случае строка 29 передаст
управление на метку Ml. При обработке цифры 5 это условие как раз выполняется,
поэтому происходит переход на метку
(строка
Каждая шестнадцатеричная цифра занимает одну тетраду. У нас две таких циф-
ры, поэтому нужно их разместить так, чтобы старшинство разрядов сохранялось.
В строках 32-33 значение в DL сдвигается на 4 разряда влево, освобождая место
в младшей тетраде под младшую
цифру.
В строке 34 в регистр AL вводится вторая шестнадцатеричная цифра С (ее ASCII-
код —
ах =
0001
0011
В строках 35-37 выясняется, попадает ли двоичный эквивалент второго сим-
вола шестнадцатеричной цифры в диапазон 0...9. Наша вторая цифра не попадает
в диапазон, поэтому для получения правильного двоичного эквивалента нужно
произвести дополнительную корректировку. Это делается в строке 38. Состояние
AL после выполнения строки 35 следующее:
ах = 0000 0001 0001 0011
В AL записано число 13h, а нужно, чтобы было
(помните о правилах записи
Так как
не попадает в диапазон 0...9, то происхо-
дит переход на строку 38. В результате работы команды вычитания в регистре AL
получается правильное значение
=
ах = 0000 0001 0000 1100
И наконец, в строке 40 сдвинутое значение в DL складывается с числом в
dx = 0000 0000 0101 0000
+
ах = 0000 0001 0000 1100
dx
0000 0000 0101 1100
Таким образом, в регистре DL получен двоичный эквивалент двух введенных
символов, изображающих двузначное шестнадцатеричное число:
=
Глава 6. Первая программа
Строки
предназначены для завершения программы и возврата управле-
ния операционной системе.
Этот пример не случайно рассмотрен столь детально. Он отражает многие спе-
цифические особенности программирования на ассемблере. На его основе постро-
ен материал следующего раздела, посвященный тому, как из исходного модуля
получить правильно функционирующий исполняемый модуль.
9h>9h>45>44>43>42>39>38>37>36>35>34>33>32>30>29>28>27>25>24>23>22>20>18>17>16>15>14>13>12>11>10>9>5>3>2>1> Do'stlaringiz bilan baham: |