<<
>>

Пример простой программы

В данном разделе рассмотрим пример простой, но полноценной программы на ас- семблере. В главе 2 при обсуждении архитектуры было перечислено большое ко- личество регистров. Как правило, большинство из них задействовано практически в любой программе.
Было бы интересно во время работы программы посмотреть (получить) их содержимое. Это нетрудно, если использовать специальную про- грамму — отладчик. Но как сделать это динамически и автономно (без помощи других программ)? Или, к примеру, как решить обратную задачу — ввести некото- рое значение с клавиатуры в регистр? Эта и подобная ей задачи являются задача- ми преобразования данных. Они довольно часто возникают на практике. Причина здесь в том, что компьютер воспринимает данные только тех типов, которые под- держиваются его системой команд. Поэтому на практике часто возникает необхо- димость преобразования данных из одного представления в другое. В этой главе в качестве примера рассмотрим частный случай решения одной из таких задач — задачи преобразования шестнадцатеричного числа из двух цифр, вводимого с кла- виатуры (то есть в символьном виде), в двоичное число. После выполнения этой операции полученное число можно использовать как операнд в двоичных ариф- метических операциях. Для начала нужно продумать алгоритм и изучить предметную область. Ввод информации с клавиатуры и вывод ее на экран осуществляются в символьном виде. Кодирование этой информации производится согласно таблице ASCII. В таблице ASCII каждый символ кодируется одним байтом. Если работа происходит с чис- лами, то при попытке их обработать сразу возникает проблема: команд для ариф- метической обработки чисел в символьном виде нет. Что делать? Выход очевиден: нужно преобразовать символьную информацию в формат, поддерживаемый ма- шинными командами. После такого преобразования нужно выполнить необходи- мые вычисления и преобразовать результат обратно в символьный вид.
Затем сле- дует отобразить информацию на мониторе. Рассматриваемая в этом разделе программа является одним из вариантов ре- шения задачи. В основу ее алгоритма положена особенность, связанная с ACSII- кодами символов соответствующих шестнадцатеричных цифр. Шестнадцатерич- ные цифры формируются из символов 0,1,..., 9, А, В, С, D, E, F, а,b, с, d, e, f, например: 12Af, 34ad. В таблице ASCII можно найти значения ASCII-кодов, соответствую- щие этим символам. На первый взгляд, непонятна популярность способа представ- ления информации в виде шестнадцатеричных чисел. Из предыдущих глав извест- но, что аппаратура компьютера построена на логических микросхемах и работает только с двоичной информацией. Если нам требуется проанализировать, например, состояние некоторой области памяти, то разобраться в нагромождении нулей и еди- ниц будет очень непросто. Для примера рассмотрим двоичную последовательность 010100010101011110101101110101010101000101001010. Это представление не очень наглядно. В главе 2 отмечалось, что оперативная память состоит из ячеек — байтов — по 8 битов. Приведенная выше цепочка битов при разбиении ее на байты будет выглядеть так: 01010001 01010111 10101101 1101010101010001 01001010. С наглядностью стало лучше, но если исследуемая область памяти окажется больше, то разобраться будет все равно сложно. Проведем еще одну операцию: каж- дый байт разобьем на две части по 4 бита — тетрады: 0101 0001 0101 0111 1010 1101 1101 0101 0101 0001 0100 1010. И вот тут проявляется замечательное свойство шестнадцатеричных чисел — каждой тетраде можно поставить в соответствие одну шестнадцатеричную цифру (табл. 6.1).
Таблица 6.1. Кодировка шестнадцатеричных цифр

Если заменить в последней полученной строке тетрады соответствующими шестнадцатеричными цифрами, то получим последовательность 51 57 ad d5 51 8а. Каждый байт теперь наглядно представлен двумя шестнадцатеричными циф- рами, что оказывается очень удобным, в частности, при работе с отладчиком.

Вернемся к нашей задаче. Если посмотреть внимательно на представление шестнадцатеричных цифр и их кодировку в АСSII-коде (табл. 6.1), то можно уви- деть полезные закономерности. К примеру, ASCII-код нуля (код символа 0) в ше- стнадцатеричном виде равен 30h. В двоичном представлении 30h записывается как ООН 0000, а соответствующее двоичное число должно быть двоичным представле- нием нуля 0000 0000. Отсюда следуют некоторые выводы. Вывод первый. Для шестнадцатеричных цифр 0...9 АСSII-код отличается от со- ответствующего двоичного представления на ООН 0000, или 30h. Поэтому для пре- образования кода символа шестнадцатеричной цифры в соответствующее двоич- ное число есть два пути: ш выполнить двоичное вычитание: (АСSII-код)h - 30h; Ж обнулить старшую тетраду байта с символом шестнадцатеричной цифры в АСSIi-коде. Видно, что с шестнадцатеричными цифрами в диапазоне от 0 до 9 все просто. Что касается шестнадцатеричных цифр а, b, с, d, e, f, то здесь ситуация несколько сложнее. Алгоритм должен распознавать эти символы и производить дополнитель- ные действия при их преобразовании в соответствующее двоичное число. Внима- тельный взгляд на символы шестнадцатеричных цифр и соответствующие им двоичные представления (см. табл. 6.1) говорит о том, для преобразования уже не- достаточно простого вычитания или обнуления старшей тетрады. Анализ таблицы ASCII показывает, что символы прописных букв шестнадцатеричных цифр отли- чаются от своего двоичного эквивалента на величину 37h. Соответствующие строч- ные буквы шестнадцатеричных цифр отличаются от своего двоичного эквивален- та на 67h. ; Отсюда следует вывод второй. Алгоритм преобразования должен различать Прописные и строчные буквенные символы шестнадцатеричных цифр и корректи- ровать значение ASCII-кода на величину 37h или 67h. Обратите внимание на то, что после записи значения шестнадцатеричной циф- ры следует символ «h». Как упоминалось в главе 4, это сделано для того, чтобы транслятор мог различить в программе одинаковые по форме записи десятичные и шестнадцатеричные числа.
В листинге 6.1 приведен исходный текст программы, которая решает задачу преобразования двузначного шестнадцатеричного числа в символьном виде в дво- ичное представление.
Листинг 6.1. Пример программы на ассемблере

Листинг 6.1(продолжение)

В предыдущих главах говорилось, что процессор аппаратно поддерживает шесть адресно-независимых областей памяти: сегмент кода, сегмент данных, сегмент стека и три дополнительных сегмента данных. Наша программа использует только пер- вые три из них. Строки 9-11 определяют сегмент данных. В строке 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 после этой пере- сылки следующее: dх = 0000 0000 ООН 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 это условие как раз выполняется, поэтому происходит переход на метку Ml (строка 31). Каждая шестнадцатеричная цифра занимает одну тетраду. У нас две таких циф- ры, поэтому нужно их разместить так, чтобы старшинство разрядов сохранялось. В строках 32-33 значение в DL сдвигается на 4 разряда влево, освобождая место в младшей тетраде под младшую шестнадцатеричную цифру. В строке 34 в регистр AL вводится вторая шестнадцатеричная цифра С (ее ASCII- код — 6Зh): ах = 0000 0001 0100 ООН В строках 35-37 выясняется, попадает ли двоичный эквивалент второго сим- вола шестнадцатеричной цифры в диапазон 0...9. Наша вторая цифра не попадает в диапазон, поэтому для получения правильного двоичного эквивалента нужно произвести дополнительную корректировку. Это делается в строке 38. Состояние AL после выполнения строки 35 следующее: ах = 0000 0001 0001 ООП В AL записано число 13h, а нужно, чтобы былоОСh (помните о правилах записи шестнадцатеричныхчисел!). Так как ОСЬ не попадает в диапазон 0...9, то происхо- дит переход на строку 38. В результате работы команды вычитания в регистре AL получается правильное значение (аl) = ОСh: ах = 0000 0001 0000 1100 И наконец, в строке 40 сдвинутое значение в DL складывается с числом в AL: dx = 0000 0000 0101 0000 + ах = 0000 0001 0000 1100 dx = 0000 0000 0101 1100 Таким образом, в регистре DL получен двоичный эквивалент двух введенных символов, изображающих двузначное шестнадцатеричное число: (dl) = 05Сh Строки 41-42 предназначены для завершения программы и возврата управле- ния операционной системе. Этот пример не случайно рассмотрен столь детально. Он отражает многие спе- цифические особенности программирования на ассемблере. На его основе постро- ен материал следующего раздела, посвященный тому, как из исходного модуля получить правильно функционирующий исполняемый модуль.

<< | >>
Источник: В. И. Юров. Assembler. Учебник для вузов. 2-е изд. 2003

Еще по теме Пример простой программы:

  1. Простой пример.
  2. Простой пример графической ректификации, используя карту страны
  3. Простой пример из обычной жизни. Авторское отступление.
  4. Простой пример из обычной жизни. Авторское отступление.
  5. Примеры жестокости по отношению к другим (эти примеры более всего относятся к семейной жизни):
  6. Программа Да и программа Нет
  7. Свободное воспроизведение программ для ЭВМ и баз данных. Декомпилирование программ для ЭВМ
  8. Г л а в а 9 О ПРОГРАММАХ
  9. Музыкальные концертные программы
  10. ИЗНАЧАЛЬНО КОРОТКАЯ ПРОГРАММА
  11. Программа телевидения
  12. О программе Астропроцессор ZET
  13. Установка программы Астропроцессор ZET
  14. Глава 1. Программа и анкета
  15. ПРОЕКТНЫЙ И ИСПОЛНИТЕЛЬНЫЙ УРОВНИ ПРОГРАММ
  16. Г л а в а 6 ПРОГРАММЫ НЕВОЗМОЖНОСТИ
  17. Первый запуск программы
  18. Г л ав а 30 ПРОГРАММЫ СТАРОСТИ. ДОЛГОЖИТЕЛИ
  19. Глава 3. ПРОГРАММА СОЦИОЛОГИЧЕСКОГО ИССЛЕДОВАНИЯ