ZX-Ревю 1993 №1-2 1992 г.

Профессиональный подход - отладчик машинного кода "TRACER".


Темы статьи: Программирование  

ПРОФЕССИОНАЛЬНЫЙ ПОДХОД

Отладчик машинного кода "TRACER"

Создание резидентных программ - один из самых интересных моментов в работе программиста. Резидентные программы работают как бы "поверх" основных и позволяют не выходя из главной программы выполнять еще какую-либо ценную задачу. Так, например, в разделе "ФОРУМ" Вам была представлена резидентная программа-русификатор, которая 50 раз в секунду проверяет нажатие комбинации клавиш SYM.SH. + ENTER и, если они не нажаты, то резидент себя не проявляет и остается "прозрачным" для пользователя.

В игровых программах резидентные процедуры как правило занимаются тем, что воспроизводят музыку одновременно с работой других процедур, а иногда им поручают обслуживание клавиатуры в поисках нажатия нужной клавиши. Нередко их используют и при организации мультипликации.

Создание резидентных программ для "Спектрума" основывается на использовании режима прерываний 2-го рода (IM2) и сегодня мы представляем Вашему вниманию еще одну полезную резидентную программу, которая поможет тем, кто программирует в машинных кодах, особенно там, где иные средства откажутся работать.

Кто не испытывал трудностей при отладке программ в машинных кодах, когда казалось бы вполне "хорошая" программа почему-то вдруг ни с того ни с сего "зависает" и никак не удается определить, почему же это происходит. Проблему отчасти решает пошаговая отладка программы при помощи мощных мониторов, таких, как, например "MONS-3", "MONS-4". Но только отчасти, так как для того, чтобы вручную "прощелкать" достаточно большую программу, требуется уйма времени, ведь программы содержат массу различных циклов и придется повторять выполнение программы в одних и тех же адресах многократно. В общем задача эта - не из простых. Пошаговая отладка - это конечно, хорошо, но неужели только этим ограничиваются возможности "влезть внутрь" программы и посмотреть, что же там происходит. Сегодня мы предлагаем читателям еще один инструмент, позволяющий заглянуть внутрь программы во время ее работы, причем в режиме реального времени. Конечно, использование приведенного метода требует определенной квалификации, но если Вы хорошо разберетесь с ним, то получите в свой арсенал инструмент, значение которого трудно переоценить.

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

Программа-отладчик машинного кода называется "TRACER". Она позволяет выводить в правой части экрана заданную информацию в шестнадцатеричном коде. Что это может быть за информация? Это зависит от Ваших требований. Что Вы зададите. Например, Вы хотите просмотреть число, записанное в какой-нибудь ячейке памяти, как оно изменяется. Или как меняется содержимое какого-то регистра. Или что записано на вершине машинного стека. Принцип работы отладчика состоит в том, что 50 раз в секунду будет происходить прерывание Вашей исследуемой программы и 50 раз в секунду интересующие Вас сведения будут выведены на экран в столбец в правой части экрана. Процедура, обслуживающая прерывание, должна формировать требуемый параметр и выдавать его на печать. От того, что конкретно Вы хотите просмотреть, зависит начало этой процедуры. В качестве примера, рассмотрим вариант кодов, который позволяет просмотреть число, записанное на вершине машинного стека. Блок кодов, который это делает, приведен в распечатке (Листинг 1), а возможный пример работы отладчика - на рис. 1.

Рис. 1

Включение отладчика в работу происходит при выполнении инициализирующей подпрограммы START, расположенной с адреса FEF7H (RANDOMIZE USR 65271). При этом происходит следующее. Вначале задается адрес в дисплейном файле, куда будет производиться вывод результатов: в регистр HL записывается адрес верхней пиксельной линии того знакоместа экрана, куда будет производиться печать. Это значение заносится в системную ячейку FF13H. Затем обнуляется другая системная ячейка 5C81H (это неиспользуемый адрес в таблице системных переменных). Здесь будет организован счетчик строк для выводимой информации. После этого происходит включение режима прерываний второго рода. В регистр I процессора записывается число FEH. Поэтому при прерывании произойдет переход на программу, адрес которой записан в ячейке памяти FEFFH. Там записан адрес FE5CH. Это начало обрабатывающей процедуры. Затем происходит переключение на режим прерываний второго рода и возврат.

Теперь 50 раз в секунду будет выполняться обслуживающая процедура. По условию, которое мы задали, она должна выдавать значение двухбайтного числа, находящегося на вершине машинного стека. Считывание этого значения происходит следующим образом. Текущее значение регистра HL сохраняется в неиспользуемой ячейке 6CB0H в таблице системных переменных. Далее интересующее нас число с вершины стека заносится в регистр HL. При этом необходимо восстановить стек в том виде, в каком он был, что выполняется при помощи обратной записи числа из HL на стек. Далее на стеке сохраняются значения всех регистров процессора, которые задействованы и будут изменены в процедуре обработки прерывания.

Теперь надо интересующее нас число (в регистре HL) вывести на печать. Это выполняется следующим образом. Проверяется значение счетчика строк 5C81H. Если не достигнут нижний край экрана, то происходит переход на процедуру CONT, а если достигнут, то для последующего вывода задается опять верхняя строка экрана путем занесения в системный счетчик FF13H исходного адреса в дисплейном файле. Счетчик строк при этом обнуляется.

Процедура CONT начинается с того, что в регистр DE наносится текущее значение адреса для вывода в дисплейном файле. Затем старший байт интересующего числа записывается в регистр A и при помощи ротации вправо старший полубайт становится на место младшего. Выполняется его печать при помощи подпрограммы PRINT, которая выполняет печать четырех младших битов, содержащихся в регистре A (в шестнадцатеричном представлении четырем битам соответствует один символ). После печати значение DE увеличивается на единицу, что соответствует переходу к следующему знакоместу. Затем в регистр A опять записывается значение из регистра H и выполняется печать младшего полубайта. Значение DE опять увеличивается на 1. Далее то же повторяется и со значением регистра L, точно так же за два приема выполняется печать двух полубайтов.

Далее, путем выполнения ротации и суммирования, в счетчике FF13H получается следующий адрес в дисплейном файле, соответствующий выводу на следующей строке. Такой способ вычисления этого адреса связан с тем, что экранная память состоит из трех сегментов и надо получить правильный результат при переходе от одного сегмента к

другому. В нашей книге "Элементарная графика" мы подробно разбирали все вопросы, связанные с выводом на экран. Поэтому, для более ясного представления о том, как все это происходит, заказывайте и читайте нашу книгу.

Листинг 1

FE5C

E2B05C INT

S/R

LD

(#5CBO),HL

Сохранение HL.

FE5F

E1

POP

HL

Получение требуемого

параметра в HL.

FE60

E5

PUSH

HL

Восстановление стека.

FE61

F5

PUSH

AF

Сохранение

FE62

C5

PUSH

BC

значений

FE63

D5

PUSH

DE

регистров.

FE64

3A815C

LD

A,(#5C81)

Переход к

FE67

3C

INC

A

следующей

FE68

32815C

LD

(#5C81),A

строке.

FE6B

FE16

CP

#16

Проверка на достижение

FE6D

200B

JR

NZ,#FE7A

конца экрана.

FE6F

111C40

LD

DE,#401C

Переход на

FE72

ED5313FF

LD

(#FF13),DE

начало экрана.

FE76

AF

XOR

A

Обнуление

FE77

32815C

LD

(#5C81),A

счетчика строк

FE7A

ED5B13FF

CONT

LD

DE,(#FF13)

Текущий адрес

в дисплейном файле.

FE7F

7C

LD

A,H

Выделение

FE7F

1F

RRA

старшего

FE80

1F

RRA

полубайта.

FE81

1F

RRA

FE82

1F

RRA

FE83

CDB9FE

CALL

#FEB9

Печать старшего

FE86

13

INC

DE

полубайта.

FE87

7C

LD

A,H

FE88

CDB9FE

CALL

#FEB9

Печать младшего

FE8B

13

INC

DE

полубайта.

FE8C

7D

LD

A,L

Выделение

FE8D

1F

RRA

старшего

FE8E

1F

RRA

полубайта.

FE8F

1F

RRA

FE90

1F

RRA

FE91

CDB9FE

CALL

#FEB9

Печать старшего

FE94

13

INC

DE

полубайта.

FE95

7D

LD

A,L

FE96

CDB9FE

CALL

#FEB9

Печать мл. полубайта.

FE99

2A13FF

LD

HL,(#FF13)

Расчет

FE9C

CB1C

RR

H

адреса

FE9E

CB1C

RR

H

в дисплейном

FEA0

CB1C

RR

H

файле

FEA2

012000

LD

BC,#0020

с учетом

FEA5

ED4A

ADC

HL,BC

сегмента

FEA7

CB14

RL

H

экрана.

FEA9

CB14

RL

H

FEAB

CB14

RL

H

FEAD

2213FF

LD

(#FF13),HL

FEB0

D1

POP

DL

Финишные операции

FEB1

C1

POP

BC

по восстановлению

FEB3

F1

POP

AF

значений

FEB3

2AB05C

LD

HL,(#5CB0)

регистров.

FEB6

C338OO

JP

#0038

Переход на RST #38

FEB9

E60F

PRINT

AND

#0F

Преобразование

FEBB

87

ADD

A,A

кода в символ

FEBC

E5

PUSH

ML

согласно

FEBD

21D7FE

LD

HL,#FED7

таблице

FEC0

0600

LD

B,#00

с учетом

FEC2

4F

LD

C,A

шестнадцати

FEC3

09

ADD

HL,BC

ричного

FEC4

46

LD

B,(HL)

представления.

FEC5

23

INC

HL

FEC6

4E

LD

C,(HL)

FEC7

C5

PUSH

BC

FEC8

E1

POP

HL

FEC9

0608

LD

B,#08

FECB

7E

PRT

LD

A, (HL)

Вывод

FECC

12

LD

(DE),A

символа

FECD

23

INC

HL

на

FECE

14

INC

D

экран.

FECF

10FA

DJNZ

#FECB

FED1

7A

LD

A,D

FED2

D608

SUB

#08

FED4

57

LD

D,A

FED5

E1

POP

HL

FEDS

C9

RET

FED7

3D803D

TABLE

DEFB

Таблица

FEDA

883D90

DEFB

для

FEDD

3D983D

DEFB

преобразования

FEE0

A03DA8

DEFB

кода

FEE3

3DB03D

DEFB

в символ

FEE6

B83DC0

DEFB

с учетом

FBE9

3DC83E

DEFB

шестнадцати-

FEEC

083E10

DEFB

ричного

FEEF

3E183E

DEFB

представления.

FEF2

203E28

DEFB

FEF5

3E30

DEFB

FEF7

211C40

START

LD

HL,#401C

Инициализирующая

FEFA

2213FF

LD

(#FF13),HL

процедура

FEFD

1802

JR

#FF01

FEFF

5CFE

ADR

DEFB

Адрес перехода по IM2.

FF01

AF

PASS

XOR

A

Продолжение

FF02

32815C

LD

(#5C81),A

инициализирующей

FF05

3EFE

LD

A,#FE

процедуры.

FF07

ED47

LD

I,A

FF09

ED5E

IM

2

FF0B

C9

RET

FF0C

ED56

STOP

IM

1

Восстанавливающая

FF0E

3E3F

LD

A,#3F

процедура.

FF10

ED47

LD

I,A

FF12

C9

RET

FF13

00

SCRP

NOP

Текущее значение адреса

FF14

00

NOP

в дисплейном файле.

После выполнения печати искомой величины, происходят финишные операции. Это восстановление со стека значений регистров процессора. При этом значение регистра HL, как мы помним, находится в ячейке 5CD0H, оттуда его и считываем. Далее - переход на адрес 0038H, как и в случае прерывания первого рода.

Непосредственно печать выполняется при помощи подпрограмм печати PRINT и PRT. Вначале зануляются старшие байты регистра A (выполняется печать только одного полубайта). Для того, чтобы обеспечить печать в шестнадцатеричном виде, используется перевод кода в символ при помощи таблицы, расположенной с адреса FED7H. В зависимости от значения кода происходит установка в регистре HL адреса в символьном наборе, с которого находится изображение этого символа. Затем процедура PRT выполняет

переписывание восьми байт из символьного набора в дисплейный файл.

В результате работы программы-отладчика в правой части экрана Вы будете видеть столбец непрерывно меняющихся цифр. Это и есть результат работы программы - числа, которые находятся на вершине стека в процессе работы программы. Они меняются достаточно быстро, но ведь все происходит в режиме реального времени. Да и к тому же это просто демонстрационный пример, показывающий возможности программы.

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

Для того, чтобы отключить отладчик, надо выполнить останавливающую подпрограмму, расположенную с адреса FF0CH (RANDOMIZE USR 65292). При этом происходит переключение на режим прерываний 1 рода - восстановление обычного режима работы "Спектрума".

И в заключении об одном ограничении на работу отладчика. Вывод на экран будет возможен только в том случае, если прерывания разрешены (EI). Если в исследуемой программе они запрещаются командой DI, то прерываний не будет и, следовательно, не будет вывода на экран.




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Мысли - Ересь: Прочитал я Heresy 8, и, к своему удивлению, обнаружил там несколько моментов.
Scene 0fF! - optical brothers news.
Party - отчет об Ижевском пати ASCII 2004.
Начало - Sheyh-Aleks из Bаndit Grоuр.
UFO II - как можно сделать побольше оружия типа 'ГАРПУН'.

В этот день...   21 ноября