Программирование на Ассемблере под DOS


Задача 2.


Задача: вывести на монитор значение регистра DL.
Народ! Давайте сразу расставим границы между КОДОМ СИМВОЛА и его НАЧЕРТАНИЕМ.
  Например, у нас F3h в DL. Как мы хотим это вывести? Как символы 'F3' или же как ASCII символ, соответствующий коду F3h? Определяемся. Если в DL у нас F3h - то надо чтоб именно 'F3' у нас на монитор и выводилась. Не 'э перевернутое', не '46 33', а именно 'F3'. Помедитируйте. Уловите разницу между 'э', '46 33' и 'F3'.

  Эту задачу мы немножко упростим :). Для начала напишем процедуру, которая выводит только младшую тетраду регистра DL (цифру "3" в нашем примере). Для этого мы обратимся к процедуре WRITE_CHAR из прошлого номера. Именно она печатает нам на монитор символ, ASCII-код которого находится в DL.
  Но тут загвоздка: в DL-код, а печатается-то символ :). А нам, собственно, именно две циферки шестнадцатеричного кода, как два символа, и нужно напечатать. Ну, или хотя бы младшую циферку этого кода...
  Решается эта задача элементарно :). Главное - это правильно ее сформулировать!
  Вот что я тут "нарисовал": ЕСТЬ НУЖНО код символ символ код ----------- ------------ 00h '?' '0' 30h 01h '?' '1' 31h 02h '?' '2' 32h 03h '?' '3' 33h 04h '?' '4' 34h 05h '?' '5' 35h 06h '?' '6' 36h 07h '?' '7' 37h 08h '?' '8' 38h 09h '?' '9' 39h 0Ah '?' 'A' 41h 0Bh '?' 'B' 42h OCh '?' 'C' 43h ODh '?' 'D' 44h OEh '?' 'E' 45h 0Fh '?' 'F' 46h

  Только во второй колонке вместо вопросительных знаков должны быть соответствующие всякие символы (посмотрите в ASCII-таблице, какие они на вид страшные!).

  Процедурка наша вот что должна делать - Всего-навсего перевести (конвертировать) тетраду в код соответствующего ей символа... Завернуто? Если разобраться, то не очень-то и завернуто.
  Смотрите: в DL у нас 03h. Хотим мы эту '3' на монитор вывести. Если вызовем WRITE_CHAR, то у нас символ "сердечко" выплюнется. А надо, чтоб символ '3' вывелся, код которого 33h.
  Соответственно и для остальных смотри по табличке.

 А теперь обратите внимание, насколько "шестнадцатеричная циферка" (тетрада) отличается от ASCII-кода, этой "циферке" соответствующего. Сам скажу: на 30h для цифр от '1' до '9', и на 37h для цифр от 'A' до 'F'. То есть "переконвертацию" мы запросто можем сделать командами add DL,30h (если тетрада в диапазоне 0...9) и add DL,37h (если тетрада в диапазоне A...F).

 Короче, вот код (пропиваю!): ;-[WRITE_HEX_DIGIT, V1]---------------------------------- ;Печатает одну шестнадцатеричную цифру (младшую тетраду DL) ;(старшая тетрада должна быть равна 0) ;На входе: DL - цифра ;На выходе: нихрена ;Прерывания: ан нэту ;Процедуры: WRITE_CHAR ;-------------------------------------------------------- WRITE_HEX_DIGIT proc push DX cmp DL,0Ah jae HEX_LETTER add DL,30h JMP WRITE_DIGIT HEX_LETTER: add DL,37h WRITE_DIGIT: call WRITE_CHAR pop DX ret WRITE_HEX_DIGIT endp

 Сначала, ессно, изменяемые регистры сохраняем (мы ж их изменяем!). (Ну, и восстанавливаем в конце процедуры (PUSH и POP соответственно)).
 Потом у нас логическое ветвление организовано. Сравниваем значение DL с "общей границей" наших двух диапазонов (команда - CMP, "граница" - 0Ah). Если это значение больше или равно 0Ah, то прыжок на метку HEX_LETTER, прибавление к DL 37h и печать цифры (WRITE_CHAR). Иначе добавляем 30h и безо всяких условий перепрыгиваем на вызов WRITE_CHAR (минуя add DL,37h то бишь).
 Все. Тестируем.

 




Начало  Назад  Вперед



Книжный магазин