четверг, 7 мая 2009 г.

Второй шаг

В предыдущем примере использовались непосредственные данные, описанные непосредственно в первых двух командах(MOV и ADD). Теперь рассмотрим аналогичный пример, в котором значения 0123h и 0025h определены в двух полях сегмента данных. Данный пример позволяет понять, как процессор обеспечивает доступ к данным посредством регистра DS и адресного смещения.
В настоящем примере определены области данных, содержащие соответственно следующие значения:

Адрес в DS Шест.знач. Номера байтов

0000 2301 0 и 1
0002 2500 2 и 3
0004 0000 4 и 5
0006 2A2A2A 6, 7 и 8

Вспомним, что один шестнадцатеричный символ занимает половину байта, два символа - байт, таким образом, например, 23h находится в байте 0 (в первом байте) сегмента данных, 01h - в байте 1 (т.е. во втором байте).
Ниже показаны команды машинного языка, которые обрабатывают эти данные:

Команда Назначение

A10000 Переслать слово (два байта),начинающееся в DS
по адресу 0000, в регистр AX.
03060200 Прибавить содержимое слова (двух байт),
начинающегося в DS по адресу 0002, к регистру AX.
A30400 Переслать содержимое регистра AX в слово,
начинающееся в DS по адресу 0004.
CB Вернуться в DOS.

Обратите внимание, что здесь имеются две команды MOV с различными машинными кодами: A1 и A3. Фактически машинный код зависит от регистров, на которые имеется ссылка, количества байтов (байт или слово), направления передачи данных (из регистра или в регистр) и от ссылки на непосредственные данные или на память.
Запускаем debug и вводим команды:

E DS:00 23 01 25 00 00 00
E DS:06 2A 2A 2A

Первая команда записывает три слова (шесть байтов) в начало сегмента данных, DS:00. Заметьте, что каждое слово вводилось в обратной последовательности, так что 0123h это 2301h, a 0025h это 2500h. Когда команда MOV будет обращаться к этим словам, нормальная последовательность будет восстановлена и 2301h станет 0123h, а 2500h – 0025h.
Вторая команда записывает три звездочки (***) для того, чтобы их можно было видеть впоследствии по команде 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. Эти команды можно выполнить, как это делалось ранее.

Смотрим на скриншот.

Обращаем внимание на то, что и у сегмента данных (DS), и у сегмента кода (CS) одинаковый адрес. И как видно сегмент кода отстоит от сегмента данных на 256 байт (100h). Правая часть дампа помогает локализовать данные, благодаря трем звездочкам (***).
Команды можно выполнить, как это делалось ранее. Перед началом исполнения выведем значения регистров при помощи команды R.
Дамп выполнения программы представлен ниже.

-e ds:00 23 01 25 00 00 00
-e ds:06 2a 2a 2a
-e cs:100 a1 00 00 03 06 02 00
-e cs:107 a3 04 00 cb
-d ds:0
13DF:0000 23 01 25 00 00 00 2A 2A-2A F0 4F 03 2C 0E 8A 03 #.%...***.O.,...
13DF:0010 2C 0E 17 03 2C 0E 54 04-01 01 01 00 02 FF FF FF ,...,.T.........
13DF:0020 FF FF FF FF FF FF FF FF-FF FF FF FF DA 0D 4E 01 ..............N.
13DF:0030 03 13 14 00 18 00 DF 13-FF FF FF FF 00 00 00 00 ................
13DF:0040 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........
13DF:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....
13DF:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
-d cs:100
13DF:0100 A1 00 00 03 06 02 00 A3-04 00 CB 00 00 00 00 00 ................
13DF:0110 00 00 00 00 00 00 00 00-00 00 00 00 34 00 CE 13 ............4...
13DF:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0170 00 00 00 00 00 00 00 00-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=13DF ES=13DF SS=13DF CS=13DF IP=0100 NV UP EI PL NZ NA PO NC
13DF: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=13DF ES=13DF SS=13DF CS=13DF IP=0103 NV UP EI PL NZ NA PO NC
13DF: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=13DF ES=13DF SS=13DF CS=13DF IP=0107 NV UP EI PL NZ NA PE NC
13DF:0107 A30400 MOV [0004],AX DS:0004=0000
-t

AX=0148 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13DF ES=13DF SS=13DF CS=13DF IP=010A NV UP EI PL NZ NA PE NC
13DF:010A CB RETF
-d ds:0
13DF:0000 23 01 25 00 48 01 2A 2A-2A F0 4F 03 2C 0E 8A 03 #.%.H.***.O.,...
13DF:0010 2C 0E 17 03 2C 0E 54 04-01 01 01 00 02 FF FF FF ,...,.T.........
13DF:0020 FF FF FF FF FF FF FF FF-FF FF FF FF DA 0D 4E 01 ..............N.
13DF:0030 03 13 14 00 18 00 DF 13-FF FF FF FF 00 00 00 00 ................
13DF:0040 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13DF:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........
13DF:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....
13DF:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
-


Желтым цветом подсвечен вывод адреса и данных из сегмента данных. Стоит обратить внимание, что здесь данные выводятся не в обратном порядке, а так же как и в регистрах в прямом, что удобно для отладки и восприятия. Так же в последнем дампе содержимого сегмента данных выделен (желтым) конечный результат – 4801h. Это данные из регистра AX помещенные в память (в обратном порядке).

Для доступа к машинной команде процессор определяет ее адрес из содержимого регистра CS плюс смещение в регистре IP.
Для доступа к данным по смещению 0002 (см. дамп) процессор определяет адрес, исходя из содержимого регистра DS (как правило) плюс смещение в операнде команды.

И еще. Чтение моего блога не может и не должно вам заменить изучение книг. На него можно опираться как на путеводную нить, но ни как на всеобъемлющий учебник по ассемблеру. Здесь я привожу лишь очень краткий конспект изученного материала.

На этом шаге я заканчиваю описание работы с debug.exe и лишь могу порекомендовать подольше повозиться с ним, внимательно прочитав и выполнив все примеры и упражнения из книги Питера Абеля, главы 2 "Машинное исполнение".

Далее я буду разбираться с тем где взять ассемблеры, чем они различаются, как их установить, как ими пользоваться и т.п. Это, к сожалению, не очень подробно описано в книгах. Так что придется разбираться самому.

Комментариев нет: