Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Assembler / P02

.pdf
Скачиваний:
55
Добавлен:
02.06.2015
Размер:
397.15 Кб
Скачать

1

3. Отладчик Debug

3.1. Пример работы с отладчиком.

Мы уже посмотрели примеры работы с отладчиком в предыдущей главе.

Теперь на очень простом примере продемонстрируем типичный сеанс работы с отладчиком.

Предположим, мы хотим изучить работу команды сложения двух целых чи-

сел. Первое слагаемое хранится в слове со смещением 200h (в текущем сегменте данных) — оно будет загружено в регистр AX, второе слагаемое — число 2 —

будет загружено в регистр BX, сумму требуется разместить в AX. Напишем с

этой целью простую программу, содержащую всего три команды.

mov ax,[200h]

; Поместить в аккумулятор содержимое

 

; слова по адресу DS:200

mov bx,2

; Поместить в регистр BX число 2 ( BX = 2)

add ax,bx

; Сложить содержимое AX и BX

 

; и поместить результат в AX ( AX += BX)

Комментарии отделены от текста программы точкой с запятой. (Рекоменду-

ется каждую фразу комментария начинать с прописной буквы. Если коммента-

рий продолжается на следующей строке, то продолжение фразы начинается со строчной буквы.) В скобках последние две команды записаны с использованием нотации языка Си — так проще запомнить, что первый операнд является при-

емником, а второй — источником. Следует понимать, что на самом деле эти три команды являются только фрагментом программы на языке ассемблера. Если мы собираемся использовать транслятор (например MASM или TASM), то к этим командам нужно добавить еще ряд директив. Однако для отладчика этих команд достаточно. Еще заметим, что вместо последних двух команд можно было написать одну: add ax,2.

Вызовем отладчик. Для этого наберем в командной строке имя утилиты debug

D:\USER\>debug

нажмем Enter и получим приглашение к диалогу — дефис.

1) Ассемблирование текста программы. В отладчике имеется мини-

ассемблер. Он переводит мнемонику команд в их машинные коды. Практически

2

все команды отладчика вызываются набором одной буквы, далее, возможно,

указываются параметры команды. Ассемблирование начинается по команде A (Assemble). Команды можно набирать и большими и малыми буквами. Команда

A имеет параметр: адрес в памяти, начиная с которого будут размещены ма-

шинные коды. (Здесь необходимо уточнение: полный адрес представлен в виде segment:offset сегмент:смещение. Как правило, мы будем указывать только смещение). Разместим коды команд, начиная со смещения 100h (этот выбор не случаен: ниже смещения 100h что-либо записывать не рекомендуется, пока вы не изучите структуру области от начала сегмента до смещения 100h — она но-

сит название префикс программного сегмента (Program Segment Prefix — PSP)).

-a100

22B6:0100 mov ax,[200] (суффикс h не указываем!)

22B6:0103 mov bx,2

22B6:0106 add ax,bx

22B6:0108 nop

22B6:0109

В ответ на ввод команды a100 отладчик выдает адрес в формате сег-

мент:смещение (на вашей машине сегментная часть адреса может быть другой

— в дальнейшем это не оговаривается) и ожидает ввод команды. Набираем ко-

манду и нажимаем клавишу Enter. Мнемоника команды немедленно переводит-

ся мини-ассемблером в машинный код (чуть ниже мы увидим, как его посмот-

реть) и отладчик выводит следующий свободный адрес — 103. Следовательно,

код команды mov ax,[200] занимает три байта (с адресами 100, 101, 102).

Мы вводим следующую команду и т.д. Завершаем программу командой nop

(нет операции). Удобство ее включения в текст программы станет ясным из дальнейшего. В ответ на адрес 109 нажимаем Enter и получаем приглашение отладчика. Обратите внимание, что все числа в debug интерпретируются как 16-

ричные, поэтому суффикс h не указывается.

Если какая-либо команда будет введена неправильно, отладчик сообщит об этом и выдаст тот же адрес (естественно — он же не смог транслировать коман-

ду):

-a100

22B6:0100 mov ax[200] (пропущена запятая)

3

^ Error

22B6:0100

Код нашей программы занимает байты с 100-го по 108-й, т.е. девять байтов.

2) Дисассемблирование кода (восстановление мнемоники команд по машин-

ному коду).

-u100L9

 

 

 

22B6:0100

A10002

MOV

AX,[0200]

22B6:0103

BB0200

MOV

BX,0002

22B6:0106

01D8

ADD

AX,BX

22B6:0108

90

NOP

 

Команда расшифровывается так: дисассемблировать (U — Unassemble),

начиная с 100-го смещения код длиной (L — Length) 9 байтов. (Можно было набрать команду в иной форме: U100 108, т.е. указать начальный и конечный адреса кода).

Полученные в результате строки имеют формат:

сегмент:смещение машинный код мнемоника

В кодах команд можно увидеть коды операндов в "перевернутом виде":

Расшифруем код A10002. A1 — код пересылки содержимого ячейки памяти в аккумулятор, 00 — младший байт и 02 — старший байт операнда-источника.

Аналогично расшифровывается код второй команды. Можно убедиться в том,

что машинные коды имеют разную длину: в нашем примере — 1, 2 и 3 байта.

3) Заполнение памяти. Перед выполнением программы нужно занести в слово памяти, расположенное по адресу DS:200, число 1. Можно было добавить это действие в нашу программу в качестве первой команды (чуть позже мы узнаем, как это сделать), но мы воспользуемся средствами отладчика. Команда

E (Enter — ввод) позволяет занести в память новое содержимое (здесь то, что выводит debug, подчеркнуто):

-e200

22B6:0200 4D.01 E2.00

(нажимаем пробельную клавишу)

Итак, мы вводим команду E и адрес. Отладчик сообщает, что в байте по ад-

ресу 200 записано число 4Dh, точка — приглашение к вводу. Набираем 01 (можно и без ведущего нуля) и нажимаем пробельную клавишу, чтобы получить

4

содержимое следующего байта (если бы старое значение байта нас устраивало,

мы сразу нажали бы пробел). По адресу 201 записано число 0E2h — заносим нуль. Завершаем команду E, нажимая Enter.

Команду E можно было ввести и в другой форме, указывая в одной строке адрес и список вводимых байтов (т.е. на этот раз мы не видим прежнее содер-

жимое ячеек памяти):

-e200 1 0

Проверим результат занесения уже знакомой командой

-d200L2

22B6:0200 01 00

Записано слово 0001 (младший байт 01, старший байт 00).

Для ввода слова проще воспользоваться уже знакомой командой A:

-a200

22B6:0200 dw 1 (Define Word — задать слово)

Здесь есть одна тонкость. Команда E offset заносит данные по адресу

DS:offset, а команда A offset — по адресу CS:offset. Но сейчас содержимое сег-

ментных регистров CS и DS совпадает.

4) Содержимое регистров. Перед тем как выполнять программу посмотрим

содержимое регистров центрального процессора. Введем команду R (Register):

-r

AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0100 NV UP EI PL NZ NA PO NC 22B6:0100 A10002 MOV AX,[0200] DS:0200=0001

Отладчик вывел три строки. В первой строке перечислены регистры общего назначения и показано их содержимое. Начальное содержимое регистров — нулевое. Только указатель стека SP содержит FFEEh, т.е. показывает на адрес,

близкий к концу сегмента. Во второй строке присутствуют сегментные реги-

стры DS, ES, SS, CS — в них хранится одинаковый сегментный адрес; счетчик команд IP содержит смещение 100h; далее перечислены текущие значения флажков в регистре флагов. Отдельные биты этого регистра устанавливаются

(1) или сбрасываются (0) по результату выполнения команд. Но отладчик пока-

зывает не содержимое регистра флагов в шестнадцатеричном представлении, а

5

значения битов в закодированной форме в виде двухбуквенных сокращений.

Сведем их в таблицу 3.1.

Таблица 3.1. Кодирование значений флагов в debug.

Флаг

Наименование

Установлен (‘1’)

Сброшен (‘0’)

OF

переполнение

OV (OVerflow)

NV (Non oVerflow)

 

 

Есть знаковое переполнение

Нет знакового переполнения

DF

направление

DN (DowN)

UP

 

 

автоуменьшение указателя при

автоувеличение указателя при

 

 

выполнении строковых команд

выполнении строковых команд

IF

прерывание

EI (Enable Interrupt)

DI (Disable Interrupt)

 

 

внешние прерывания разрешены

внешние прерывания запрещены

SF

знак

NG (NeGativ)

PL (PLus)

 

 

результат отрицательный

результат неотрицательный

ZF

ноль

ZR (ZeRo)

NZ (Non Zero)

 

 

результат нулевой

результат ненулевой

AF

вспомогательный

AC (Adjust Carry)

NA (Non Adjust carry)

 

перенос

произошел перенос из младшей

переноса из младшей тетрады не

 

 

тетрады

было

PF

четность

PE (Parity Even)

PO (Parity Odd)

 

 

сумма битов младшего байта чет-

сумма битов — нечетная

 

 

ная

 

CF

перенос

CY (Carry Yes)

NC (Non Carry)

 

 

установлен флаг переноса

флаг переноса сброшен

В третьей строке представлены адрес, код и мнемоника команды, которая будет выполняться первой при запуске на выполнение. Ее сегментный адрес хранится в CS, а смещение в IP (именно этой информацией воспользовался от-

ладчик, чтобы отобразить команду). Кроме того, в третьей строке показано со-

держимое ячейки памяти, на которую ссылается один из операндов команды.

5) Выполнение программы "по шагам". В этом режиме после каждой коман-

ды выполнение будет приостанавливаться. Для этого вводим команду T (Trace

— трассировка). Выполняется команда, адрес которой содержится в IP, и пока-

зывается информация, как при подаче команды R.

-t

AX=0001

BX=0000

CX=0000

DX=0000

SP=FFEE BP=0000 SI=0000 DI=0000

DS=22B6

ES=22B6

SS=22B6

CS=22B6

IP=0103 NV UP EI PL NZ NA PO NC

22B6:0103

BB0200

MOV BX,0002

Обратите внимание, что изменилось содержимое только двух регистров:

AX — в него загружено значение 1, и IP — в нем адрес следующей выполняе-

мой команды. Сама команда показана в третьей строке. Флаги не изменились.

6

-t

AX=0001 BX=0002 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0106 NV UP EI PL NZ NA PO NC

22B6:0106

01D8

ADD AX,BX

-t

 

 

AX=0003 BX=0002 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000

DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0108 NV UP EI PL NZ NA PE NC

22B6:0108

90

NOP

Только теперь (после команды add ax,bx) изменилось содержимое реги-

стра флагов. Правда это коснулось только одного флага PF (в младшем байте результата (03h=00000011b) установлено два бита, то есть четное число битов).

6) Внесение изменений в программу: в регистр BX запишем –1. Заменим вторую команду нашей программы.

-a103

22B6:0103 mov bx,-1

22B6:0106

Проверим результат изменений (на всякий случай, хотя и так видно, что

длина команды не изменилась):

-u100L9

 

 

22B6:0100 A10002

MOV AX,[0200]

 

22B6:0103 BBFFFF

MOV BX,FFFF

(дополнительный код числа –1)

22B6:0106 01D8

ADD AX,BX

 

22B6:0108 90

NOP

 

Вновь выполним трассировку. Но сейчас в IP содержится 108h, поэтому первая команда трассировки выглядит иначе, чем раньше: после знака равенства указываем стартовый адрес.

-t=100

AX=0001 BX=0002 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0103 NV UP EI PL NZ NA PE NC 22B6:0103 BBFEFF MOV BX,FFFE

-t

.............

7) Изменение содержимого регистров. Если наша цель — изучение коман-

ды add, то проще изменять значения регистров средствами отладчика непо-

средственно перед выполнением команды add. Вновь воспользуемся командой

R, но теперь укажем имя регистра:

7

-rax

AX 0000

:-2

^ Error

Отладчик показывает содержимое AX и запрашивает новое содержимое.

Вводим число –2. Отладчик воспримет это как ошибку. Нужно сначала полу-

чить дополнительный код –2. Его можно узнать с помощью отладчика. Команда

H <1-е число> <2-е число> вычисляет сумму и разность аргументов-слов:

-h0 2

0002 FFFE (т.е. 0 + 2 = 0002 и 0 – 2 = 0FFFEh)

Теперь введем в AX дополнительный код числа –2.

-rax

AX 0000

:fffe

Изменим BX

-rbx

BX FFFE

:3

А теперь выполним трассировку только команды сложения.

-t=106

AX=0001 BX=0003 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0108 NV UP EI PL NZ AC PO CY 22B6:0108 90 NOP

8) Выполнение всей программы:

-g=100 108

AX=0000 BX=FFFF CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0108 NV UP EI PL ZR AC PE CY 22B6:0108 90 NOP

Итак, использована команда G (Go — прогон), далее после знака равенства указываем стартовый адрес, затем адрес точки останова (теперь мы видим поль-

зу команды nop — именно ее адрес служит адресом точки останова). Заметим,

что команда g=100 приведет скорее всего к зависанию программы (лучше не проверять это!). Действительно, после наших четырех команд в оперативной памяти хранится "мусор", который будет интерпретироваться процессором как коды команд.

8

9) Сохранение файла с программой на диске. Для этого выполним последо-

вательность действий:

а) дадим файлу имя pr1.com. Введем команду N (Name — имя)

-npr1.com

(отладчик создает исполняемые файлы только типа .com — не .exe!)

б) в регистры BX и CX занесем длину программы в байтах. BX:CX — длин-

ное беззнаковое целое: в BX — старшие разряды, в CX — младшие разряды.

Типичная ошибка: забывают занести в BX нуль. В результате на диске образует-

ся очень большой файл.

-rbx

BX FFFF :0

-rcx CX 0000 :9

Еще раз напомним, что диапазон адресов 100 – 108 имеет длину 9 байтов.

в) введем команду записи на диск W (Write — писать).

-w

Writing 00009 bytes

Отладчик сообщил количество записанных байтов.

10) Выход из отладчика. Вводим команду Q (Quit — мы с отладчиком "кви-

ты")

-q

D:\USER\>_

Убедитесь, что в текущем каталоге действительно имеется файл pr1.com

размера 9 байтов. Запускать его на выполнение из командной строки бессмыс-

ленно по двум причинам:

программа не отображает результаты работы на экране, проследить ее работу можно только средствами отладчика;

в программе нет команд, обеспечивающих возврат в DOS, поэтому после наших четырех команд начнет выполняться "мусор" с непредсказуемыми последствиями.

9

11) Отладка программы, хранящейся в файле. Мы хотим еще поработать с нашей программой, записанной в файле pr1.com. Начать работу можно двумя способами.

а) Указать имя файла в командной строке при запуске debug:

D:\USER\> debug pr1.com

-r

AX=0000 BX=0000 CX=0009 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=22B6 ES=22B6 SS=22B6 CS=22B6 IP=0100 NV UP EI PL NZ NA PO NC 22B6:0100 B80100 MOV AX,0001

В BX:CX записан размер считанной программы.

б) Загрузить нужный файл в оперативную память с помощью команд debug:

D:\USER\> debug

-n pr1.com (назовем имя)

-L (Load — загрузка содержимого файла в оперативную память)

Программа считана с диска. С ней можно работать. После внесения измене-

ний в программу может возникнуть желание сохранить новый вариант про-

граммы на диске. Для записи на диск достаточно установить нужные BX:CX и

ввести команду W, т.к. имя файла уже задано.

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

чика и типовых "связках" команд, дадим систематическое изложение. Отладчи-

ки, которые мы будем изучать позже, не будут сопровождаться столь подроб-

ным изложением, т.к. для них можно получить информацию в Справке (Help)

программного продукта.

3.2. Параметры команд отладчика.

Запуск отладчика возможен в двух вариантах:

1)D:\USER\> debug

2)D:\USER\> debug <имя файла>

При втором варианте запуска отладчик загружает содержимое файла в ниж-

ний доступный сегмент (при этом файл с расширением .com загружается в этом сегменте со смещением 100h).

После запуска debug на выполнение пользователь получает приглашение (-)

и может вводить команды. Формат команды:

10

буква [параметр(ы)] Здесь буква — первая буква команды, например ко-

манда F — (Fill —заполнять). параметр(ы) — перечень параметров, которые могут быть разделены пробелами или запятыми. Разделитель обязателен между последовательностью шестнадцатеричных величин. Буквы могут быть пропис-

ными и строчными.

Перечислим типы параметров: величина — от одной до четырех шестна-

дцатеричных цифр (суффикс h не указывается); байт — две шестнадцатеричные цифры; адрес — можно задать тремя способами:

1)сегмент:смещение, например, 057D:0020, или 57D:20 (ведущие нули можно не указывать);

2)сегментный регистр:смещение, например, cs:109

3)смещение. Если команда работает с машинными инструкциями (команды

A,G,L,T,U,W), подразумевается сегментный регистр CS, если работа идет с

данными — DS.

область — диапазон адресов; его можно задать двумя способами

1)адрес смещение, например, cs:100 110 (Неверно: cs:100 cs:110 — второй параметр не является смещением).

2)адресLвеличина, где величина — размер области в байтах, например

cs:100L11 задает точно такую же область длиной 17 байтов, как и в предыдущем примере.

строка — цепочка символов, заключенная в одинарные или двойные ка-

вычки (если кавычки встречаются внутри строки, их следует удваивать).

Примеры: 'Эта ''строка'' правильная'

"this ""string"" is okay"

список — последовательность байтов и/или строк.

пример: "Hello!",d,a,'$'

3.3. Команды отладчика Сгруппируем команды по их функциональному назначению. 1) Работа с данными.

1.1) D [область]

Dump — дамп

Эта команда бала разобрана ранее.

Соседние файлы в папке Assembler