© Иван Рощин, Москва
| ZXNet | : 500:95/462.53 |
| : bestview@mtu-net.ru | |
| WWW | : http://www.ivr.da.ru |
Дата последнего редактирования: 10.05.2003.
Наверняка у каждого программиста при отладке своего творения возникала
мысль: хорошо бы в любой момент работы отлаживаемой программы при нажатии
определённой комбинации клавиш выйти в отладчик (например, чтобы посмотреть
значения переменных), а затем как ни в чём не бывало вернуться к выполнению
программы. В
В этом отладчике существует возможность поставить в отлаживаемой программе точку останова, при достижении которой происходит выход в STS. Рассмотрим подробнее, что происходит при установке точки останова (с помощью клавиши «W»), и при выходе в STS, когда отлаживаемая программа достигла точки останова.
При установке точки останова:
Когда выполняемая программа достигает точки останова:
Приведённой информации вполне достаточно, чтобы написать фрагмент
программы, который при нажатии некоторой комбинации клавиш (например,
«SS+D» от слова «Debugger») обеспечивает
вход в STS с возможностью дальнейшего продолжения работы отлаживаемой
программы. Нужно только знать адреса ADR_W, ADR_B и ADR_OST. Отмечу, что в
разных версиях STS эти адреса различаются, а адрес ADR_OST зависит ещё и от
расположения резидентной части STS в памяти. Чтобы найти ADR_OST, достаточно
посмотреть, какую команду STS поставит при нажатии клавиши «W».
Чтобы найти ADR_B, можно, скажем, записать по
Привожу адреса для пяти известных мне версий STS (при условии, что резидент находится по адресу #5B90):
| ADR_W | ADR_B | ADR_OST | |
|---|---|---|---|
| STS 3.2 | #DFC3 | #DFE4 | #5B98 |
| STS 3.3 | #DFC3 | #DFE4 | #5B98 |
| STS 4.1 | #E064 | #E07C | #5B9B |
| STS 4.3 | #E06E | #E088 | #5B9B |
| STS 5.1 | #E02E | #E038 | #5B9B |
Приведённый ниже фрагмент вы можете вставить в отлаживаемую программу, например, после процедуры опроса клавиатуры или в другом часто выполняемом месте. Хочу заметить, что адрес его расположения в памяти должен быть меньше #C000, т.к. в этом фрагменте переключаются банки ОЗУ.
ADR_W EQU #E02E ;Эти адреса даны для
ADR_B EQU #E038 ;STS версии 5.1, если резидент
ADR_OST EQU #5B9B ;находится по адресу #5B90.
BANK_S EQU #1F ;Банк STS.
BANK_D EQU #18 ;Банк отлаживаемой программы.
LD BC,#7FFE ;Адрес порта клавиатуры.
IN A,(C) ;Проверяем, нажата ли "Symb.Shift".
BIT 1,A ;Если да, флаг Z установлен.
JR NZ,NEXT_C ;Если не нажата, выходим...
LD B,#FD ;Изменяем адрес порта.
IN A,(C) ;Аналогично проверяем
BIT 2,A ;клавишу "D".
JR NZ,NEXT_C ;Если не нажата, выходим...
LD BC,#7FFD ;Устанавливаем банк, в
LD A,BANK_S ;котором находится STS.
OUT (C),A
;Имитируем для STS точку останова:
LD HL,ADR_B ;Здесь хранятся 3 байта,
;запомненные при установке
;предыдущей точки останова.
LD DE,(ADR_W) ;Адрес, по которому их надо
;разместить (обязательно ниже #C000)!
LD BC,3
LDIR ;Восстанавливаем 3 байта.
LD HL,NEXT_C ;Адрес первой команды, которая
LD (ADR_W),HL ;будет выполнена после выхода
;из STS, записываем в ячейки
;ADR_W..ADR_W+1 (в них STS хранит
;адрес, по которому была установлена
;точка останова).
LD DE,ADR_B ;В ячейках ADR_B..ADR_B+2 STS хранит
LD BC,3 ;3 байта, расположенные по адресу
LDIR ;точки останова.
LD A,BANK_D ;Возвращаем банк, который был
OUT (C),A ;до этого.
JP ADR_OST ;Точка останова.
NEXT_C ... ;Отсюда начнется выполнение после
;выхода из STS.
После нажатия «SS+D» и выхода в STS все регистры принимают значения, которые были на момент прерывания программы, так что можно будет продолжить её выполнение.
В процессе отладки можно поставить в программе точку останова, лишь бы в момент работы приведённого выше фрагмента (когда удаляется старая точка останова и ставится новая) адрес старой точки останова был ниже #C000.
Вы можете продолжить выполнение отлаживаемой программы с того места, где
она была остановлена, например, в пошаговом режиме («SS+Z»,
«SS+X», «SS+T») или используя окно Trace, или с
помощью комбинации клавиш «SS+J» (в версиях STS ниже 4.0
используйте «J», установив адрес запуска равным содержимому PC,
или используйте комбинацию «SS+K», но при этом останется экран
STS). Если вы хотите вернуться в ассемблер, Бейсик или
Если ваша программа зависает неизвестно почему, STS тоже может
вам помочь. Для этого вы должны встроить фрагмент, подобный описанному выше, в
процедуру обработки прерываний
Ограничение на адрес расположения процедуры в памяти такое же, как и у ранее описанного фрагмента.
ADR_W EQU #E02E ;Эти адреса даны для STS
ADR_B EQU #E038 ;версии 5.1, если резидент
ADR_OST EQU #5B9B ;находится по адресу #5B90.
BANK_S EQU #1F ;Банк STS.
BANK_D EQU #18 ;Банк отлаживаемой программы.
EX (SP),HL ;Адрес возвращения из прерывания
LD (M1+1),HL ;записываем в ячейки M1+1 и M1+2.
EX (SP),HL
PUSH AF ;Сохраняем в стеке
PUSH BC ;значения регистров.
PUSH DE
PUSH HL
PUSH IX
PUSH IY
EXX
EX AF,AF'
PUSH AF
PUSH BC
PUSH DE
PUSH HL
CALL USER ;Здесь может быть опрос
;клавиатуры, вызов музыки,
;в общем, всё что хотите.
LD BC,#7FFE ;Адрес порта клавиатуры.
IN A,(C) ;Проверяем, нажата ли "Symb.Shift".
BIT 1,A ;Если да, флаг Z установлен.
JR NZ,NEXT_C ;Если не нажата, выходим...
LD B,#FD ;Изменяем адрес порта.
IN A,(C) ;Аналогично проверяем
BIT 2,A ;клавишу "D".
JR NZ,NEXT_C ;Если не нажата, выходим...
LD BC,#7FFD ;Устанавливаем банк, в
LD A,BANK_S ;котором находится STS.
OUT (C),A
;Имитируем для STS точку останова:
LD HL,ADR_B ;Здесь хранятся 3 байта,
;запомненные при установке
;предыдущей точки останова.
LD DE,(ADR_W) ;Адрес, по которому их надо
;разместить.
LD BC,3
LDIR ;Восстанавливаем 3 байта.
M1 LD HL,0 ;Адрес первой команды, которая
LD (ADR_W),HL ;будет выполнена после выхода
;из STS, записываем в ячейки
;ADR_W..ADR_W+1 (в них STS хранит
;адрес, по которому была установлена
;точка останова).
LD DE,ADR_B ;В ячейках ADR_B..ADR_B+2 STS хранит
LD BC,3 ;3 байта, расположенные по адресу
LDIR ;точки останова.
LD BC,#7FFD
LD A,BANK_D ;Возвращаем банк, который был
OUT (C),A ;до этого.
POP HL ;Восстанавливаем
POP DE ;значения регистров.
POP BC
POP AF
EXX
EX AF,AF'
POP IY
POP IX
POP HL
POP DE
POP BC
POP AF
EX (SP),HL ;Убираем из стека
POP HL ;адрес возврата.
EI
JP ADR_OST ;Точка останова.
;После выхода из STS выполнение программы будет
;продолжено с того места, где оно было прервано
;процедурой обработки прерывания.
NEXT_C ;Если вызов STS не понадобился:
POP HL ;Восстанавливаем
POP DE ;значения регистров
POP BC
POP AF
EXX
EX AF,AF'
POP IY
POP IX
POP HL
POP DE
POP BC
POP AF
EI
RET ;и выходим из прерывания.
При отладке программ часто используют совместно STS и ассемблер (TASM, MASM, ZX ASM и т.п.), что очень удобно. Если в вашу программу встроен один из описанных выше фрагментов, вы должны обратить особое внимание на то, как вы запускаете программу на выполнение. Если из STS, всё будет нормально в любом случае. Если же программа запускается из ассемблера или Бейсика, у вас может не получиться выйти в STS при нажатии «SS+D», или вы выйдете в STS, но не сможете продолжить выполнение программы.
Известно, что пошаговое выполнение команд процессора в STS осуществляется тремя способами: с помощью комбинаций клавиш «SS+Z», «SS+X» и «SS+T». Попробую рассказать об особенностях этих способов и о том, когда лучше использовать каждый из них.
«SS+T» отладчик ставит после выполняемой команды, которая не может находиться в ПЗУ, точку останова и запускает отлаживаемую программу. По этой точке программа возвращается через резидент в STS. «SS+T» удобно применять для трассировки DJNZ, но для трассировки подпрограмм (CALL, RST) лучше этот способ не использовать, т.к. может случиться неприятность. Это видно на следующем примере:
#8000: CALL #8004 #8003: RET #8004: LD A,7 #8006: OUT 254,A #8008: RET |
Эта программа должна установить белый цвет бордюра. Если выполнить её в пошаговом режиме с помощью «SS+Z», можно убедиться, что именно это она и делает. Однако, если выполнить её, нажав «SS+T», ожидаемого результата вы не получите. Для того, чтобы понять, почему это происходит, подробнее разберём алгоритм работы отладчика при нажатии «SS+T»:
Всё бы хорошо, но в рассматриваемом случае 3 байта команды JP накладываются на адрес, по которому передаётся управление в команде CALL #8004. В результате этого реально выполняется следующая последовательность команд:
#8000: CALL #8004 #8004: SBC A,E #8005: LD E,E #8006: OUT (254),A #8008: RET #8003: JP #5B9B |
Разумеется, всё вышесказанное относится и к команде процессора DJNZ, так что «SS+T» нужно применять с осторожностью. Вот, например, какая может быть ситуация при трассировке DJNZ:
#8000: LD B,#00 #8002: LD A,(#800A) #8005: OUT (#FE),A #8007: DJNZ #8002 #8009: RET #800A: DB 0 ;Этот байт будет испорчен. |
Теперь поговорим о пошаговой трассировке (окно Trace). В этом окне есть параметр Trace Call. Если он включен, отладчик будет заходить «внутрь» процедуры при каждом выполнении команды CALL или RST (эмулируется «SS+Z»), а если выключен выполнять её с помощью прямого запуска из резидента («SS+X»). Мне кажется, была бы полезной возможность независимо от значения Trace Call отключить трассировку подпрограмм, адреса которых выходят за заранее определённые границы. Эти границы должны указываться в окне Trace. Например, если нижняя граница равна #4000, а верхняя #FFFF, то отладчик не будет заходить «внутрь» всех подпрограмм ПЗУ. Но так как этой возможности в STS нет, остаётся только надеяться, что она будет в одной из следующих версий.
|
Другие мои статьи об отладчике STS:
|