13C6:0110 90 NOP
-T
AX=0000 BX=0290 CX=0148 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13C6 ES=13C6 SS=13C6 CS=13C6 IP=0111 NV UP EI PL ZR NA PO NC
13C6:0111 CB RETF
-
__________________________________________________________________________
Рис.2.1. Трассировка машинных команд.
Команда R показывает также по смешению 0100 первую выполняемую
машинную команду. Регистр CS на рис.2.1 содержит значение CS=13C6 (на
разных компьютерах оно может различаться), а машинная команда выглядит
следующим образом:
13C6:0100 B82301 MOV AX,0123
CS=13C6 обозначает, что начало сегментов кода находится по
смещению 13C6 или точнее 13C60. Значение 13C6:0100 обозначает 100
(шест.) байтов от начального адреса 13C6 в регистре CS.
B82301 - машинная команда, введенная по адресу CS:100.
MOV AX,0123 - ассемблерный мнемонический код, соответствующий
введенной машинной команде. Это есть результат операции
дисассемблирования, которую обеспечивает отладчик для более простого
понимания машинных команд. В последующих главах мы будем кодировать
программы исключительно в командах ассемблера. Рассматриваемая в
данном случае команда обозначает пересылку непосредственного значения
в регистр AX.
В данный момент команда MOV еще не выполнена. Для ее выполнения
нажмите клавишу T (для трассировки) и клавишу Return. В результате команда
MOV будет выполнена и отладчик выдаст на экран содержимое регистров,
флаги, а также следующую на очереди команду. Заметим, что регистр AX
теперь содержит 0123. Машинная команда пересылки в регистр AX имеет код B8
и за этим кодом следует непосредственные данные 2301. В ходе выполнения
команда B8 пересылает значение 23 в младшую часть регистра AX, т.е.
однобайтовый регистр AL, а значение 01 - в старшую часть регистра AX, т.е.
в регистр AH:
AX: | 01 | 23 |
Содержимое регистра IP:0103 показывает адрес следующей выполняемой
команды в сегменте кодов:
13C6:0103 052500 ADD AX,0025
Для выполнения данной команды снова введите T. Команда прибавит 25 к
младшей (AL) части регистра AX и 00 к старшей (AH) части регистра AX, т.е.
прибавит 0025 к регистру AX. Теперь регистр AX содержит 0148, а регистр IP
0106 - адрес cледующей команды для выполнения.
Введите снова команду T. Следующая машинная команда пересылает
содержимое регистра AX в регистр BX и после ее выполнения в регистре BX
будет содержаться значение 0148. Регистр AX сохраняeт прежнее значение
0148, поскольку команда MOV только копиpует данные из одного места в
другое.
Теперь вводите команду T для пошагового выполнения каждой оставшейся
в программе команды. Следующая команда прибавит cодержимое регистра AX к
содержимому регистра BX, в последнем получим 0290. Затем программа
скопирует содержимое pегистра BX в CX, вычтет AX из CX, и вычтет AX из
него самого. После этой последней команды, флаг нуля изменит свое
состояние c NZ (не нуль) на ZR (нуль), так как результатом этой команды
является нуль (вычитание AX из самого себя очищает этот регистр в 0).
Можно ввести T для выполнения последних команд NOP и RET, но это мы
сделаем позже. Для просмотра программы в машинных кодах в сегменте кодов
введите D для дампа:
D CS:100
В результате отладчик выдаст на каждую строку экрана по 16 байт
данных в шест. представлении (32 шест. цифры) и в символьном представлении
в коде ASCII (один символ на каждую пару шест. цифр). Представление
машинного кода в символах ASCII не имеет смысла и может быть игнорировано.
В следующих разделах будет рассмотрен символьный дамп более подробно.
Первая строка дампа начинается с 00 и представляет содержимое ячеек
от CS:100 до CS:10F. Вторая строка представляет cодержимое ячеек от CS:110
до CS:11F. Несмотря на то, что ваша программа заканчивается по адресу
CS:111, команда Dump aвтоматически выдаст на восьми строках экрана дамп с
адреса CS:100 до адреса CS:170.
При необходимости повторить выполнение этих команд сбросьте
содержимое регистра IP и повторите трассировку снова. Введите R IP,
введите 100, а затем необходимое число команд T. После каждой команды
нажимайте клавишу Return.
На рис.2.2 показан результат выполнения команды D CS:100. Обратите
внимание на машинный код с CS:100 до 111 и вы обнаружите дамп вашей
программы; следующие байты могут содержать любые данные.
__________________________________________________________________________
-D CS:100
13C6:0100 B8 23 01 05 25 00 8B D8-03 D8 8B CB 2B C8 2B C0 .#..%.......+.+.
13C6:0110 90 CB 8D 46 14 50 51 52-FF 76 28 E8 74 00 8B E5 ...F.PQR.v(.t...
13C6:0120 B8 01 00 50 FF 76 32 FF-76 30 FF 76 2E FF 76 28 ...P.v2.v0.v..v(
13C6:0130 E8 88 15 8B E5 BF 36 18-12 FF 36 16 12 8B 76 28 ......6...6...v(
13C6:0140 FF 74 3A 89 46 06 E8 22-CE 8B E5 30 E4 3D 0A 00 .t:.F.."...0.=..
13C6:0150 75 32 A1 16 12 2D 01 00-8B 1E 18 12 83 DB 00 53 u2...-.........S
13C6:0160 50 8B 76 28 FF 74 3A A3-16 12 89 1E 18 12 E8 FA P.v(.t:.........
13C6:0170 CD 8B E5 30 E4 3D 0D 00-74 0A 83 06 16 12 01 83 ...0.=..t.......
-Q
__________________________________________________________________________
Рис.2.2. Дамп кодового сегмента.
Для завершения работы с программой DEBUG введите Q (Quit - выход). В
результате произойдет возврат в DOS и на экране появится приглашение A>
или C>. Если печатался протокол работы с отладчиком, то для прекращения
печати cнова нажмите Ctrl/PrtSc.
ПРИМЕР МАШИННЫХ КОДОВ: ОПРЕДЕЛЕНИЕ ДАННЫХ
________________________________________________________________
В предыдущем примере использовались непосредственные данные,
описанные непосредственно в первых двух командах (MOV и ADD). Теперь
рассмотрим аналогичный пример, в котором значения 0123 и 0025 определены в
двух полях сигмента данных. Данный пример позволяет понять как компьютер
обеспечивает доступ к данным посредством регистра DS и адресного смещения.
В настоящем примере определены области данных, содержащие
cоответственно следующие значения:
Адрес в DS Шест. знач. Номера байтов
0000 2301 0 и 1
0002 2500 2 и 3
0004 0000 4 и 5
0006 2A2A2A 6, 7 и 8
Вспомним, что шест. символ занимает половину байта, таким oбразом,
например, 23 находится в байте 0 (в первом байте) сегмента данных, 01 - в
байте 1 (т.е. во втором байте).
Ниже показаны команды машинного языка, которые обрабатывают эти
данные:
Команда Назначение
A10000 Переслать слово (два байта), начинающееся в DS по адресу
0000, в регистр AX.
03060200 Прибавить содержимое слова (двух байт), начинающегося в DS
по адресу 0002, к регистру AX.
A30400 Переслать содержимое регистра AX в слово, начинающееся в DS
по адресу 0004.
CB Вернуться в DOS.
Обратите внимание, что здесь имеются две команды MOV с pазличными
машинными кодами: A1 и A3. Фактически машинный код зависит от регистров,
на которые имеется ссылка, количества байтов (байт или слово), направления
передачи данных (из регистра или в регистр) и от ссылки на
непосредственные данные или на память.
Воспользуемся опять отладчиком DEBUG для ввода данной программы и
анализа ее выполнения. Когда отладчик выдал свое дефисное приглашение, он
готов к приему команд.
Сначала введите команды E (Enter) для сегмента данных:
E DS:00 23 01 25 00 00 00 (Нажмите Return)
E DS:06 2A 2A 2A (Нажмите Return)
Первая команда записывает три слова (шесть байтов) в начало сегмента
данных, DS:00. Заметьте, что каждое слово вводилось в обратной
последовательности, так что 0123 есть 2301, a 0025 есть 2500. Когда
команда MOV будет обращаться к этим cловам, нормальная последовательность
будет восстановлена и 2301 станет 0123, а 2500 - 0025.
Вторая команда записывает три звездочки (***) для того, чтобы их
можно было видеть впоследствии по команде D (Dump) - другого назначения
эти звездочки не имеют.
Введем теперь команды в сегмент кодов, опять начиная с адреса CS:100:
E CS:100 A1 00 00 03 06 02 00
E CS:107 A3 04 00 CB
Теперь команды находятся в ячейках памяти от CS:100 до CS:10A. Эти
команды можно выполнить как это делалось ранее. На рис.2.3 показаны все
шаги, включая команды E. На экране дисплея должны появиться такие же
результаты, хотя адреса CS и DS могут различаться. Для пересмотра
информации в сегменте данных и в сегменте кодов введите команды D (Dump)
соответственно:
для сегмента данных: D DS:000 (Return)
для сегмента кодов: D CS:100 (Return)
Сравните содержимое обоих сегментов с тем, что вводилось и с
изображенным на рис.2.3. Содержимое памяти от DS:00 до DS:08 и от CS:100
до CS:10A должно быть идентично рис.2.3.
__________________________________________________________________________
D>DEBUG
-E DS:23 01 25 00 00
-E DS:2A 2A 2A
-E CS:100 A1 00 00 03 06 02 00
-E CS:107 A3 04 00 CB
-D DS:0
13C6:0000 23 01 25 00 00 9A 2A 2A-2A F0 F5 02 2C 10 2E 03 #.%...***...,...
13C6:0010 2C 10 BD 02 2C 10 B1 0D-01 03 01 00 02 FF FF FF ,...,...........
13C6:0020 FF FF FF FF FF FF FF FF-FF FF FF FF EF 0F 64 00 ..............d.
13C6:0030 61 13 14 00 18 00 C7 13-FF FF FF FF 00 00 00 00 a...............
13C6:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13C6:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........
13C6:0060 20 20 20 20 20 20 20 20 00 00 00 00 00 20 20 20 .....
13C6:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
-R
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13C6 ES=13C6 SS=13C6 CS=13C6 IP=0100 NV UP EI PL NZ NA PO NC
13C6:0100 A10000 MOV AX,[0000] DS:0000=0123
-T
AX=0123 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13C6 ES=13C6 SS=13C6 CS=13C6 IP=0103 NV UP EI PL NZ NA PO NC
13C6:0103 03060200 ADD AX,[0002] DS:0002=0025
-T
AX=0148 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13C6 ES=13C6 SS=13C6 CS=13C6 IP=0107 NV UP EI PL NZ NA PE NC
13C6:0107 A30400 MOV [0004],AX DS:0004=9A00
-T
AX=0148 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13C6 ES=13C6 SS=13C6 CS=13C6 IP=0108 NV UP EI PL NZ NA PO NC
13C6:010A CB RETF
-D DS:0
13C6:0000 23 01 25 00 00 9A 2A 2A-2A F0 F5 02 2C 10 2E 03 #.%...***...,...
13C6:0010 2C 10 BD 02 2C 10 B1 0D-01 03 01 00 02 FF FF FF ,...,...........
13C6:0020 FF FF FF FF FF FF FF FF-FF FF FF FF EF 0F 64 00 ..............d.
13C6:0030 61 13 14 00 18 00 C7 13-FF FF FF FF 00 00 00 00 a...............
13C6:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13C6:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........
13C6:0060 20 20 20 20 20 20 20 20 00 00 00 00 00 20 20 20 .....
13C6:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
-Q
__________________________________________________________________________
Рис.2.3. Трассировка машинных команд.
Теперь введите R для просмотра содержимого регистров и флагов и для
отображения первой команды. Регистры содержат те же значения, как при