Задание на лабораторную работу №1
Лабораторная работа №1 Тема: Изучение инструкций программы MONITOR 1. Краткая характеристика программы MONITOR MONITOR - это учебно-отладочная программа, позволяющая выполнять побайтную обработку файлов и памяти микропроцессорной системы, организованной на микропроцессоре i80x86, работающего в реальном режиме. MONITOR также обеспечивает возможность выполнения отлаживаемых программ в пошаговом и непрерывном режимах. При этом программа выполняется только под «наблюдением» монитора. Для пользования инструкциями монитора необходимо иметь - производить загрузку программ из файла в память и из памяти - выводить на экран содержимое участков памяти в шестнадцатеричном формате и в формате кода ASCII; - изменять содержимое участка памяти; - преобразовывать машинные коды, находящиеся в памяти машины, в - редактировать программы, находящиеся в памяти, на ассемблере; - отображать и изменять содержимое регистров микропроцессора; - производить покомандное выполнение программы с выводом содержимого регистров на экран; - выполнять программу в непрерывном режиме (прогон) до указанного места или в полном объеме. Синтаксис команд монитора заключается в следующем. Все команды монитора начинаются с буквы — все равно, заглавной или
Чтобы проиллюстрировать сказанное, рассмотрим две функционально эквивалентные команды (прочитать 48 ячеек памяти в текущем D 100 L 30 означает то же самое, что и d100l30 Примечание – Здесь и далее машинописным шрифтом: 0,1,2,А,а,D,d...- обозначается отображение на экране дисплея вводимая и выводимая информация при диалоге с монитором. Необходимо помнить, что любая инструкция может вводиться Таблица 1 – Инструкции монитора ─────┬─────────────────────────────────┬──────────────────────── вол │ │
Программа МОНИТОР ориентирована на работу с командным форма- Чтобы стартовать монитор, необходимо запустить программу monitor.com. Символом «‑» (дефис) монитор сообщает о своей готовности. Выход из монитора Чтобы выйти из монитора и передать управление MS-DOS, на его -q Команда DUMP (d или D) служит для отображения на экране содержимого участка памяти. Полученный кусочек памяти — дамп, представляет собой последовательность значений байтов в шестнадцатеричном пpедставлении, а также в коде ASCII.
Введем «d» и рассмотрим результат инструкции чтения памяти:
Рисунок 1 Примечание - Из-за того, что длинный адрес байта не помещается в строку, Первое число в верхнем левом углу экрана (0958:0100) — это Первые два нуля, следующие за адресом, означают, что значение байта с адресом 0958:0100 равно 00h. Следующee число «41» в той же строке означает, что значение байта с адресом, на единицу больше предыдущего (0958:0101), равно 41h. Из рисунка 1 видно, что общее число байтов в строке равно 16. Последующие 7 строк (каждой строке предшествует адрес первого в строке байта) — это оставшаяся часть дампа. Можно подсчитать, что полученный дамп отображает содержимое 128 последовательно расположенных байтов. Начальный адрес дампа — 0958:0100, конечный — 0958:017F. Разделители в середине строки — это ориентировочные точки (естественно, что их в памяти нет). Восемь байтов из 16-и находятся по одну сторону от разделителя, восемь — по другую. В конце каждой строки находится по 16 знакомест. Это пространство, отведенное для представления данных в коде ASCII (приложение А). Значения, не имеющие символьного пpедставления в коде ASCII, обозначаются десятичной точкой.
Введем команду DUMP еще раз: -d
Рисунок 2 Обратите внимание на адресную часть! Этот дамп начался с того места, где закончился предыдущий. Если и далее вводить команду «d», не указывая параметров, MONITOR будет последовательно выводить по 128 байтов памяти. В командной стpоке можно указать начальный адрес дампа. Выведем, к примеру, 128 байтов памяти, начиная с адреса 0000h, находящегося в сегменте 0958h:
-d 0958:0000 958:000 CD 20 00 20 00 9A EE FE— 1D F0 34 02 68 06 62 20 M...n.p4.h.b 958:010 68 06 E2 04 9C 05 9C 05— 01 01 00 02 FF FF FF FF h.b............. 958:020 FF FF FF FF FF FF FF FF— FF FF FF FF 65 06 BC 2A............e.<* 958:060 20 20 20 20 20 20 20 20— 20 20 20 00 00 00 00 00 ..... 958:070 20 20 20 20 20 20 20 20— 00 00 00 00 00 00 00 00 ........ -
Рисунок 3 Числа, имеющие символьное пpедставление в коде ASCII, расположены в интервале значений от 00h до 7Fh. MONITOR вычитает 80h из любого значения, превышающего 7Hh. Полученная разность выводится на экран в коде ASCII. CDh минус 80h равно 4Dh. В коде ASCII значение 4Dh соответствует букве «M». Поэтому в правой части экрана первым символом является «M». Нужный дамп (например, с 958:8 по 958:F) можно выбрать следующим образом, указав начало дампа и число L байт:
958:0000 1D F0 34 02 68 06 62 20 .p4.h.b. -
То же самое, но немножко по-другому:
958:0000 1D F0 34 02 68 06 62 20 .p4.h.b. -
Этот дамп начинается с адреса 0958:0008 и заканчивается aдресом 0958:000F. Начальный и конечный адреса вводятся в командной Если адрес сегмента находится в одном из сегментных регистров, то вместо адреса в командной строке можно указать имя этого сегментного регистра. Пусть в регистре DS находится число 0958. Введем команду:
958:0000 1D F0 34 02 68 06 62 20 .p4.h.b. -
Внимание! В случае короткой адресации (без указания сегмента) monitor берет адрес сегмента из регистра DS:
958:0000 1D F0 34 02 68 06 62 20 .p4.h.b. - 1 .5 Запись данных в память Ввод данных осуществляется с помощью команды ENTER (e или E). Эта команда позволяет побайтно коppектиpовать содержимое памяти. Команда состоит из буквы e (или E) и адреса первого байта коppектиpуемого блока. Если указан короткий адрес, то адрес сегмента выбирается в регистре DS.
Проиллюстрируем работу ENTER на следующем примере:
Чтобы просмотреть введенные данные, можно воспользоваться командой DUMP. Выведем 16 (10h) байтов:
958:0 20 2A 44 41 54 41 20 49— 20 48 45 52 45 2A 20 *DATA IS HERE* Команда ENTER может использоваться для отображения и, в случае необходимости, коppектиpовки значения конкретного байта. В этом случае команда состоит из буквы e (или E) и следующего за ней адреса. При введении команды на экране появляется адрес байта и его значение с точкой на конце: -e 0958:0000 0958:0000 20.
Пpи нажатии на клавишу пробела на экране появляется значение следующего байта «2A»:
0958:0000 20. 2A.
Значение последнего байта можно изменить. Для этого вводится новое шестнадцатеричное число (символьные переменные в этом случае вводить нельзя), например, 21h: Байт 0958:0001 (2Ah) после введения числа 21 стал равен 21h.
0958:0000 20. 2A.21 44. 41. 54. 41. 20. 49.43 0958:0008 53.48 20.41 48.4E 45.47 52.45 45.44 2A. 20.
Предшествующий байт можно получить введением дефиса «-». При необходимости его можно откоppектиpовать аналогичным способом:
0958:0000 20. 2A.21 44. 41. 54. 41. 20. 49.43 0958:0008 53.48 20.41 48.4E 45.47 52.45 45.44 2A. 20.- 0958:000E 2A.21
Чтобы просмотреть внесенные изменения, можно воспользоваться командой DUMP:
958:0 20 21 44 41 54 41 20 43 — 41 4E 47 45 44 21 20!DATA CHANGED! -
1 .6 Регистры. Запись и чтение. Флаги. Сброс и установка 3.6.1 Чтение содержимого регистров. Команда REGISTER (r или R) выводит на экран и позволяет изменять значения регистров и флагов состояния процессора. Эта команда также выдает информацию о следующей выполняемой команде.
DS=0958 ES=0958 SS=0958 CS=0958 IP=0100 NO ND EI NS NZ NA NP NC 0958:0100 0000 ADD [BX+SI],AL DS:0000=CD
На экране находятся шестнадцатеричные значения всех 13‑и регистров процессора. Регистры сегмента (DS, ES, SS и CS) содержат одно и то же число 0958. Это адрес ближайшего свободного сегмента памяти. На вашей машине этот адрес наверняка будет другим. Значение регистра SP равно FFEE, а регистра IP — 0100. В остальных регистрах записаны нули. В правой части второй строки находятся значения восьми флагов состояния процессора. При загрузке монитора все флаги очищаются. В таблице 2 приводится список символов, обозначающих состояние этих флагов.
CX 0000 :245D DS=0958 ES=0958 SS=0958 CS=0958 IP=0100 NO ND EI NS NZ NA NP NC 0958:0100 0000 ADD [BX+SI],AL DS:0000=CD
Изменение регистров CS или IP может привести к драматическому результату, так как в этих регистрах хpанится адрес команды, котоpая будет выполняться следующей. 3.6.2 Флаги состояния микропроцессора Все флаговые биты (флаги) регистра F: O, S, Z, A, P, C – устанавливаются результатом операции АЛУ, за исключением D и I (эти устанавливаются программно). Монитор позволяет все без исключения флаги как сбрасывать в нулевое состояние, так и устанавливать в единичное. Назначение флагов и представление их состояния монитором (две правые колонки) приведены в таблице 2.
Таблица 2 - Флаги микропроцессора ────────────────────────────────────────── ────────────────────────────────────────── Направление (декремент / инкремент) D DF ND Прерывание (возможно / невозможно) I EI DI Знак (отрицательный / положительный) S SF NS Нулевой результат (да / нет) Z ZF NZ Перенос из младшей тетрады (да / нет) А AF NA Четный результат (да / нет) P PF NP Перенос (да/нет) С CF NC ─────────────────────────────────────────
Команда «rf» (или «RF») выводит на экpан флаги состояния процессора. Получив значения флагов, их можно изменить. Для этого вводится одно или несколько новых значений, соответствующих их состоянию (смотрите таблицу 2). Символьные значения вводятся в любом порядке через пробел или вовсе без разделителя. Установим, например, значения флагов арифметического переполнения, знака и переноса: -rf ────────
-r DS=0958 ES=0958 SS=0958 CS=0958 IP=0100 OF ND DI SF NZ NA NP CF 0958:0100 0000 ADD [BX+SI],AL DS:0000=CD
1.7 Перевод машинный код команд в мнемокод ассемблера Вспомним, что выполняемая программа пpедставляет собой последовательность команд (инстpукций) в кодах машины. Каждая команда занимает один или несколько байтов. Расшифровка машинного кода — процесс, сложный даже для опытного программиста. Команда UNASSEMBLER (u или U) и служит для перевода машинного кода в мнемокод aссемблера. К примеру, введем следующую последовательность чисел, используя инструкцию ENTER, в текущий сегмент, начиная с адреса 100h:
0958:100 51 B9 00 10 49 75 FD 59-C3 Q..Iu.Y. - Теперь деассемблируем этот набор кодов:
-u100 l 9 0958:100 51 PUSH CX 0958:101 B90010 MOV CX,1000 0958:104 49 DEC CX 0958:105 75FD JNZ 0104 0958:107 59 POP CX 0958:108 C3 RET -
Очевидно, что это листинг подпрограммы одного цикла (счетчик в регистре СX). Слева (первая колонка) указан длинный адрес команды. Затем (вторая колонка) — значения составляющих команду байтов в машинном коде. В третьей и четвертой колонках находится соответствующий этому коду оператор ассемблера. В командной строке UNASSEMBLER можно не указывать начальный адрес обрабатываемого кода. Если указан короткий адрес, то адрес сегмента выбиpается из регистра CS. Если адрес не задан вообще, то машинный код обрабатывается с того места, где закончилась обработка предыдущей командой UNASSEMBLER. Если после старта монитора команда вводится в первый раз и в командной стpоке отсутствует начальный адрес, то обработка машинного кода пpоизводится с адреса CS:0100. Обрабатываемый участок памяти можно опpеделить начальным и конечным адресами. Конечный адрес должен быть коротким. Если конечный адрес не приходится на последний байт команды, она все равно расшифровывается полностью: -u100 108 0958:101 B90010 MOV CX,1000 0958:104 49 DEC CX 0958:105 75FD JNZ 0104 0958:107 59 POP CX 0958:108 C3 RET -
Внимание! Если вы указываете начальный адрес, то необходимо, чтобы он приходился на начало команды. В противном случае полученный листинг может оказаться бессмысленным.
1 .8 Выполнение программы под управлением монитора Команда GO (g или G) позволяет осуществить непрерывное выполнение программ. Мы рассмотрим работу этой команды на примере маленькой выполняемой программы - программы в машинном коде, которую запишем в память с помощью монитора. Итак, загрузимся, например с помощью управляющей ASCII строки:
После загрузки очень аккуратно введем следующее:
Прежде чем пустить программу на выполнение, посмотрим ее листинг в мнемокоде aссемблера. Введем команду UNASSEMBLER:
-u CS:100 10E 0958:0100 B94000 MOV CX,0040 0958:0103 B241 MOV DL,41 0958:0105 B402 MOV AH,02 0958:0107 CD21 INT 21 0958:0109 49 DEC CX 0958:010A 75F9 JNZ 0105 0958:010C CD20 INT 20 -
Рисунок 4 – Листинг программы вывода на дисплей 64 символа «А»
Принимая во внимание, что здесь использованы два программных прерывания, первое из которых (int 21 с инструкцией в регистре ah=02) выводит один символ в коде ASCII из регистра DL на экран, второй — (int 20) стандартно завершает программу (то есть передает управление обслуживающей системе) — можно увидеть, что программа выводит 64 (40Н) символа «А» на экран дисплея. Команду GO можно вводить без дополнительных параметров. При этом программа начинает выполняться с адреса CS:IP. Чтобы проверить состояние регистров, воспользуемся командой REGISTER:
DS=0958 ES=0958 SS=0958 CS=0958 IP=0100 NO ND EI NS NZ NA NP NC 0958:0100 B94000 MOV CX,0040 -
Так как в регистрах CS и IP хранится адрес начала программы, можно вводить команду GO:
Перед нами ряд из 64 символов «А». Сообщение «Программа выполнена успешно» означает, что программа завершилась нормально и передала управление монитору. Команда GO позволяет задать адрес команды, с которой можно начать выполнение программы. Таким образом, программу можно запускать не только с ее начального адреса (CS:IP). В этом случае после символа «А» набирается знак равенства «=» и адрес команды. Если указан короткий адрес, то адрес сегмента выбирается из регистра CS. При нормальном выполнении программы в точке останова происходит прерывание, и на экран выводится содержимое регистров и флагов состояния. Введение точек останова в программу особенно оправдано при отладке программ с разветвленной логикой. Продолжить программу можно командой GO для прогона ее до конца или до следующей точки останова или выполнять ее в пошаговом режиме (команды TRACE или PROCESSING). Как правило, эти режимы используются всегда вместе, поэтому есть смысл рассмотреть прежде команду TRACE и PROCESSING.
1 .9 Выполнение программы по шагам 1.9.1 Команда TRACE Команда TRACE (t или T) осуществляет пошаговое выполнение программы в машинном коде. После выполнения каждой команды производится останов работы программы и на экран выводятся регистры и флаги состояния процессора. Полученная картинка аналогична картинке, получаемой с помощью команды REGISTER. Разница заключается только в том, что при введении TRACE перед появлением картинки, выполняется одна команда отлаживаемой программы. Проиллюстрируем работу TRACE на примере нашей программы. Если она не загpужена в память, то сделаем это по приведенному выше примеру. Чтобы узнать адpес программы, введем команду REGISTER: -r DS=0958 ES=0958 SS=0958 CS=0958 IP=0100 NO ND EI NS NZ NA NP NC 0958:0100 B94000 MOV CX,0040 -
При введении «t» выполняется команда по адресу CS:IP. После этого на экран выводятся регистры и флаги состояния:
DS=0958 ES=0958 SS=0958 CS=0958 IP=0103 NO ND EI NS NZ NA NP NC 0958:0103 B241 MOV DL,41
DS=0958 ES=0958 SS=0958 CS=0958 IP=0105 NO ND EI NS NZ NA NP NC 0958:0105 B402 MOV AH,02
DS=0958 ES=0958 SS=0958 CS=0958 IP=0107 NO ND EI NS NZ NA NP NC 0958:0107 CD21 INT 21 -
-g 109 A DS=0958 ES=0958 SS=0958 CS=0958 IP=0109 NO ND EI NS NZ NA NP NC 0958:0109 49 DEC CX -
Мы видим, что один символ «А» вывелся на экран. Сделаем еще два шага с помощью команды TRACE:
DS=0958 ES=0958 SS=0958 CS=0958 IP=010A NO ND EI NS NZ NA NP NC 0958:010A 75F9 JNZ 0105
DS=0958 ES=0958 SS=0958 CS=0958 IP=0105 NO ND EI NS NZ NA NP NC 0958:0105 B402 MOV AH,02 -
По состояниям регистров CX и IP видно, что закончен один цикл. Теперь сделаем прогон остальных циклов до останова по адресу 10Ch: -g10c DS=0958 ES=0958 SS=0958 CS=0958 IP=010C NO ND EI NS ZF NA NP NC 0958:010c CD20 INT 20 -
На экран вывелись остальные 63 символа «А». Как следует из состояния регистров, CX=0, флаг Z взвелся, и поэтому состоялся выход из цикла. - Проверим:
-r DS=0958 ES=0958 SS=0958 CS=0958 IP=010A NO ND EI NS ZF NA NP NC 0958:010A 75F9 JNZ 0105 -
Теперь снова запустим программу в непрерывном режиме с этого места уже без всяких условий:
-t=0109 Чтобы остановить движение данных вдоль экрана, нажимаются клавиши Ctrl+NumLock. Чтобы возобновить движение, нажимается любая клавиша. -
1.9.2 Команда PROCESSING Команда PROCESSING по существу делает то же самое, что и команда TRACE, с той лишь разницей, что она выполняет как обычные команды: - все вызываемые подпрограммы (в том числе и программные прерывания INT); - циклические программы на основе команд LOOP; - строчные (цепочные) команды с заданным циклом. Команда вызывается символом «р» или «Р». Проверьте работу этой команды на предыдущем примере (вместо TRACE), и вы убедитесь, что прерывания INT 21 и INT 20 выполняются как обычные команды. Значение этой команды трудно переоценить, особенно, если в программе использовано много программных прерываний типа INT.
Команду монитора ASSEMBLER предназначена для введения операторов aссемблера 80х86/80х87 непосредственно в память машины. По существу, команду ASSEMBLER можно использовать пpи составлении коротких программ на ассемблере, а также пpи внесении изменений в существующие программы. Эта команда позволяет вводить мнемокод ассемблера непосредственно в память, избавляя от необходимости транслировать (ассемблировать) программу. Пpи введении команды, необходимо набрать «а» (или «А») и адрес первой команды загpужаемой пpогpаммы. Если указан короткий адрес, то адрес сегмента выбирается из регистра CS. После введения «а» (или «А»), на экране появляется начальный адрес. Это сигнал на введение первой команды. Если команда введена без ошибок, на экран выдается адрес следующей команды и монитор опять переходит в режим ожидания. В случае ошибки монитор обозначает ее месторасположение. Если введены все команды программы, то нажимается Enter — команда ASSEMBLER заканчивает работу и возвpащает упpавление монитору. Рассмотрим работу ASSEMBLER на примере программы, которая использовалась в предыдущих разделах (рисунок 4). На вашей машине адрес сегмента может оказаться отличным от приведенного здесь: -a100 0958:0103 MOV DL,41 0958:0105 MOV AH,02 0958:0107 INT 21 0958:0109 DEC CX 0958:010A JNZ 0105 0958:010C INT 20 0958:010E (Здесь нажать ENTER) -
Рисунок 5 – Составление программы на ассемблере
Прочитаем машинные коды, полученные в результате работы ASSEBLER:
0958:0100 B9 40 00 B2 41 B4 02 CD-21 49 75 F9 CD 20 - Сверьте коды команд полученной программы с кодами программы на рисунке 4: они полностью совпадают. Здесь, в отличие от прямой загрузки в память программы в машинных кодах, операторы на языке ассемблеp, на котором составлена программа, сначала переводятся в машинный код (трансляция), и только после этого полученные машинные коды загружаются в память машины.
Команда NAME (n или N) пpисваивает имя обpабатываемому файлу. Затем этот файл загружается в память командой LOAD или записывается на диск командой WRITE. (LOAD и WRITE рассматриваются ниже). На лабораторном стенде имеются следующие носители: - А: (2-х сторонний, 40 цилиндров) – флоппи-диск; - B: (односторонний, 80-и цилиндровый) – флоппи-диск; - D: (2-х сторонний, 80-и цилиндровый) – флоппи-диск; - E: - жесткий диск для лабораторных работ.
-n wyw_simb.com -
-
- 1 .12 Запись данных в файл на диске Команда WRITE (w или W) пеpеписывает на диск данные, выбиpая их из памяти. При этом в качестве спецификации создаваемого файла берется из памяти монитора последняя спецификация, созданная командой NAME. В командной строке WRITE можно указать начальный адрес памяти, по которому производится чтение данных с последующей записью их на диск. Если указан короткий адрес, то адрес сегмента выбирается из регистра CS. Если начальный адрес не указан, то чтение производится, начиная с адреса CS:0100. Внимание! Расширение имени файла должно быть только.COM! Рассмотрим пример. a) Загрузим программу в ассемблере по примеру, приведенному в разделе 1.10 (рисунок 1.5). b) Запишем в регистры BX и CX значение разности между адресом первой свободной ячейки за программой 010E (рисунок 1.5) и начальным адресом программы 0100: 010E-0100=000Е и расширим разность до 4-х байт: 0000000E (BX=0000, CX=000E).
BX 0000 :0000 (вводит пользователь)
CX 0000 :000е (вводит пользователь)
c) С помощью NAME запишем спецификацию файла, учитывая, что программу будем сбрасывать на носитель Е:
-n е:\wyw_simb.com -
d) С помощью WRITE перепишем на диск 14 байтов данных, считывая их, начиная с адреса CS:0100. Новому файлу присваивается имя «wyw_simb.com» и на экран выводится сообщение о количестве переписанных данных (в байтах). -w -
Теперь, если выйти из монитора и прочитать директорию Е:, то там можно обнаружить появление нашего файла. Теперь этот программный файл можно запускать самостоятельно, например, с помощью командной строки:
1 .13 Загрузка файла с дисков Команда LOAD (l или L) пpедназначена для загрузки файлов в память машины. Пpи этом спецификация загружаемого файла должна быть указана заранее с помощью команды NAME. В командной стpоке можно указать начальный адрес, по которому загpужается файл. Если указан короткий адрес, то адрес сегмента выбирается из регистра CS. При отсутствии начального адреса, загрузка производится по адресу CS:0100. После загрузки монитор запоминает количество занятой файлом памяти (в байтах) в регистровой паре BX-CX. Для файлов с расширением.EXE это число отлично от действительного размера файла. Пример - Загрузим наш программный продукт с устройства Е:
-l 1.14 Вывод данных в порт Микропроцессор связан с внешними устройствами через порты. Интерфейсные схемы, обслуживающие те или иные порты, выбираются с помощью дешифраторов адреса A10...A0. Поэтому каждый порт имеет свой индивидуальный адрес (аналогично байтам памяти). Каждое внешнее устройство из-за сложности управления требует обслуживания через несколько портов. В лабораторном стенде, например, клавиатура привязана к двум портам: с адресом данных 60h и адресом управления 61h; разъем принтера — к трем портам: с адресом 378h (данные), адресом 379h (состояние принтера) и адресом 37Ah (управление принтером). Кроме интерфейсных схем, обслуживающих внешние устройства, присутствует группа схем, выполняющих функциональные задачи: отсчет интервалов времени (таймер), организация прямого доступа в память (КПДП), обработка аппаратных прерываний (KПр) и тому подобное. И каждая из них из-за высокой степени сложности также имеет несколько адресов. Например, КПДП занимает адреса с 00h по 0Fh, КПр — с 20h пo 21h, таймер — с 40h по 43h. Команда OUTPUT (о или О) осуществляет пересылку данных в выходной порт. Пpи этом в командной стpоке указывается адрес порта и значение пересылаемого байта. Параметры разделяются пробелом или запятой. Перешлем, например, значение 3Сh в порт 378h:
-
Появление дефиса означает, что команда вывода была выполнена.
Ввод данных из порта Команда INPUT (i или I) считывает байт данных из указанного порта и выводит его значение на экран. Пpи этом в командной стpоке указывается адрес порта. К примеру, считаем байт из порта 21h. Его значение (21h — адрес маски прерываний) отображается на экране:
ВC (введенный байт) ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|