ZX-Ревю 1997 №1-2 1997 г.

Форум - доступ к порту #iF в TR-DOS 5.03.


(С) Иван Рощин, Москва, 1996г. ДОСТУП К ПОРТУ #iF В TR-DOS 5.03.

Программируя дисковые операции на уровне портов ввода-вывода, Вы неизбежно столкнетесь с необходимостью получить значение регистра состояния из порта #1F. Как же это сделать? Известо, что адреса регистров микроконтроллера появляются в адресном пространстве только в момент работы дисковой системы. Из бей-сик-системы регистры недоступны. Не сделано, также, никаких попыток обеспечить прямой доступ к ним из дисковой системы. Несмотря на это, "достать" микроконтроллер все-таки возможно, для этого используются "обрывки" программ ОС. По другому, к сожалению, не получится.

ДОС

ВВЕРХ

ВНИЗ

ВЛЕВО

ВПРАВО

ОГОНЬ

ОЧИСТКА

ЦВЕТ

ОЧИСТКА ЭКРАНА

МЛАДШИЙ

СТАРШИЙ

МАКСИМАЛЬНЫЙ

МИНИМАЛЬНЫЙ

УСТАНОВИТЬ

ВЫКЛЮЧИТЬ

ПЕРЕМЕННАЯ

ЧИСЛО

ЗНАК

МУЗЫКА

ЗВУК

ШРИФТ

КОМПРЕССОР

ДЕКОМПРЕССОР

КОДИРОВЩИК

ДЕКОДЕР

ДЕКОМПРЕССОР

ДЛЯ

К, ДО

ПРОСТРАНСТВО

МЕСТО

АРХИВ

РАЗАРХИВАТОР ФОРМАТ КАДР СКАНЕР

ДЕМОНСТРАЦИЯ ВЫХОД РАСШИРЕНИЕ ИНИЦИАЛИЗАЦИЯ РАБОТА ТЕСТ ЦИФРА

Опубликованная в "ZX-РЕВЮ" 96/4-5 информация о том, что в ПЗУ TR-DOS 5.03 по адресу #09BF стоит последовательность команд IN A,(#1F) и RET, не подтвердилась. В фирменной версии ПЗУ по этому адресу Вы можете найти лишь коды #FF. Еще один экзотический способ доступа к портам (передаем управление в ПЗУ TR-DOS за несколько тактов до прерывания 2-го рода, а процедура обработки прерывания получает считанное из порта значение) теоретически неплох, но практически вряд ли осуществим (а если промежуток между двумя прерываниями непостоянен, этот метод вообще неприменим).

В книге А.Ларченко и Н.Родионова "ZX Spectrum & TR-DOS для пользователей и программистов" приводится следующий алгоритм считывания регистра состояний микроконтроллера:

• -записать 0 в регистр дорожки;

• -записать #0А в регистр сектора;

• -записать 1 в регистр D;

• -вызвать подпрограмму по адресу #3F33;

• -взять из регистра В значение регистра состояний;

• -Заслепи» »У/1

• -восстановить в регистрах дорожки и сектора исходные значения.

Я пользовался этим способом, и все вроде бы было нормально. Но я стал замечать, что в некоторых случаях при обращении к процедуре считывания регистра состояния компьютер зависал или сбрасывался. Пытаясь найти причину, я выяснил следующее:

АЛГОРИТМ РАБОТАЕТ НЕПРАВИЛЬНО, ЕСЛИ 0-Й БИТ РЕГИСТРА СОСТОЯНИЙ УСТАНОВЛЕН В 1 (КОНТРОЛЛЕР ЗАНЯТ ВЫПОЛНЕНИЕМ КАКОЙ-ЛИБО КОМАНДЫ).

Действительно, рассмотрим все возможные случаи работы подпрограммы TR-DOS по адресу #3F33 в зависимости от считанного из порта #1F числа, а заодно разберемся, почему перед ее вызовом необходимо устанавливать

описанные выше параметры.

проверяем 4-й бит

1) Биты 0-6

равны нулю

JR NZ,#3F4B

(Х0000000).

;условие не выполняется

#3F33: IN

A,(#1F)

LD А,В

LD

В,А

AND #4

AND

#7F

JR Z,#3FA0

; выделяем биты 0-6

;условие выполняется

RET

Z

; выход

#3FA0: DEC D

2) б-й бит равен 1, 0-й бит равен 0

; получили 0

(Х1ХХХХХ0).

JP Z,#3F48

#3F33: IN

А,(# 1F)

;условие выполняется

LD

В,А

AND

# 7F

#3F48: LD HL,#29E2

RET

Z

LD A,#D0

;не выходим

OUT (#1F),A

LD

HL,#29D8

LD А, В

AND

#40

AND #1

проверяем 4-й бит

{проверяем 0-й бит

JR

NZ,#3F4B

JP NZ,#3EE7

;условие выполняется

;условие не выполняется

IN A,(#3F)

#3F4B: LD A.#D0 OUT (#1F),A LD А, В AND #1 проверяем 0-й бит

JP NZ,#3EE7 ;условие не выполняется

IN A,(#3F) ; регистр дорожки равен 0 OR А JR NZ,#3F5F ;условие не выполняется

IN A,(#5F) ; регистр сектора равен #0А СР #0А RET Z ;условие выполняется 3) 6-й бит равен 0, 2-й бит равен 0-й бит равен 0, какой-то из бит 1,3,4,5 равен 1. (X0XXX0X0). #3F33: IN A,(#1F) LD В,A AND #7F RET Z ;условие не выполняется

LD HL,#29D8 AND #40

ZX~Pe«i6 97/1-3 форум

;регистр дорожки равен О OR А JR NZ,#3F5F ;условие не выполняется

IN A,(#5F) регистр сектора равен #0А CP #0А RET Z ;условие выполняется 4) 0-й бит равен 1 (ХХХХХХХ1).

В этом случае, независимо от значения других битов, управление будет передано по адресу #ЗЕЕ7. Там расположена процедура, портящая значение некоторых переменных TR-DOS и завершающая свою работу так:

LD LD LD LD JP

#01F3:

SP,(#5D1C) HL,(#5D1A) BC,(#5D0F) В,0 (HL)

Так как в ячейках #5D1A-#5D1D, вообще говоря, могут содержаться произвольные значения, дальнейшее выполнение программы непредсказуемо. Вдобавок, значение, считанное из порта #1F и хранящееся в регистре В (ради которого все и затевалось), будет потеряно.

Теперь я приведу написанную мной процедуру, которая правильно (всегда!) определяет значение регистра состояния. При своей работе она не изменяет значение ни одной системной переменной. TR-DOS.

•ПРОЦЕДУРА STATUS ВОЗВРАЩАЕТ СОДЕРЖИМОЕ РЕГИСТРА СОСТОЯНИЯ. ;ВХОД: А -СОДЕРЖИМОЕ РЕГИСТРА ДОРОЖКИ, ; В -СОДЕРЖИМОЕ РЕГИСТРА СЕКТОРА, ; КОТОРЫЕ БУДУТ УСТАНОВЛЕНЫ ПОСЛЕ ; ВЫХОДА ИЗ ПРОЦЕДУРЫ. ;ВЫХОД: А -ЗНАЧЕНИЕ, СЧИТАННОЕ ИЗ ПОРТА #1F. ПРЕРЫВАНИЯ ПОСЛЕ ВЫХОДА ЗАПРЕЩЕНЫ!

STATUS DI LD

; ДО РОЖКА LD LD

; СЕКТОР

LD

LD

LD

DEC

LD

СОХРАНЯЕМ СОДЕРЖИМОЕ ЯЧЕЕК, КОТОРЫЕ ;МОГУТ БЫТЬ ИСПОРЧЕНЫ:

LD

A,(#5D0E)

LD

(ST1 + 1 ),A

LD

A,(#5D0C)

LD

(ST2+1 ),A

LD

A,(#5CB6)

LD

(ST3t1),A

LD

A,(#5D1F)

LD

(ST4+1),A

LD

A,(#5C3A)

LD

(ST5+1),A

LD

A,(#5D17)

LD

(ST6+1),A

LD

HL,(#5D1A)

LD

(ST7+D.HL

LD

HL,(#5D1C)

LD

(ST8+D.HL

LD

HL,(#5CF8)

LD

(ST9+1),HL

ОСТАНАВЛИВАЕМ СОДЕРЖИМОЕ НЕКОТОРЫХ ;ЯЧЕЕК ДЛЯ ПРАВИЛЬНОЙ РАБОТЫ:

A,#FF (#5D0C),A (#5D1F),A A

(#5D0E),A

(RG_D+1),A А,В

(RG_S+1 ),А

CALL TO_WG93 LD A,#OA ;#A В РЕГИСТР LD C,#5F ; СЕКТОРА CALL TO_WG93 LD D, 1 LD IX,16179 CALL TO.DOS ОПРЕДЕЛИЛИ #1F

ТЕПЕРЬ ВОССТАНАВЛИВАЕМ СОДЕРЖИМОЕ РЕГИСТРОВ ДОРОЖКИ И

СЕКТОРА:

RG D LD

A,0

LD

C,#3F

CALL

TO WG93

RG S LD

A,0

LD

C,#5F

CALL

TO WG93

{ВОССТАНАВЛИВАЕМ РАНЕЕ ЗАПОМНЕННОЕ {СОДЕРЖИМОЕ ЯЧЕЕК:

ST1

LD

A,0

LD

(#5D0E),A

ST2

LD

A.O

LD

(#5D0C),A

ST3

LD

A,0

LD

(#5CB6),A

;СЮДА БУДЕТ ПЕРЕДАНО УПРАВЛЕНИЕ, ЕСЛИ ;0-Й БИТ РЕГИСТРА СОСТОЯНИЙ РАВЕН 1:

S_SPEC POP ВС ; СОДЕРЖИ МОЕ ПОРТА

LD HL,(#5D1C) LD DE.12 ВОССТАНАВЛИВАЕМ

ADD HL.DE УКАЗАТЕЛЬ

LD SP.HL

СТЕКА

JR

RG_D

TO_WG93 TO DOS

LD IX,#2A53

PUSH IX JP #3D2F

Я думаю, нет лучшего способа объяснить, как работает эта процедура, чем показать процесс ее выполнения, начиная с момента вызова подпрограммы по адресу #3F33. При этом выберем именно такой случай, когда 0-й бит регистра состояния равен 1: #3F33: IN A,(#1F) {допустим, считано #FF LD В, А AND #7F RET Z ;не выходим

форум

LD

A,#F4

ST4

LD

A.O

LD

(#5CB6),A

LD

(#5D1F),A

ST5

LD

A,0

LD

HL.S SPEC

LD

(#5C3A),A

LD

(#5D1A),HL

ST6

LD

A,0

LD

HL.O

LD

(#5D17),A

ADD

HL.SP

ST7

LD

HL.O

LD

DE.-12

LD

(#5D1A),HL

ADD

HL.DE

ST8

LD

HL,0

LD

(#5D1C),HL

LD

(#5D1C),HL

ST9

LD

HL,0

LD

A,0

LD

(#5CF8),HL

;0 В РЕГИСТР

LD

C,#3F

LD

А,В

{ДОРОЖКИ

RET

LD HL,#29D8 AND #40 проверяем 4-й бит

JR NZ,#3F4B ;условие выполняется

#3F4B: LD A,#D0 OUT (#1F),A LD А, В AND #1 проверяем 0-й бит

,JP NZ,#3EE7 •.условие выполняется

#FE

NZ,#03CD

AF

#ЗЕЕ7:

CALL

#272B

#272В:

LD

A,# 1A

JR

#2731

#2731:

LD

(#5C3A),A

RET

#ЗЕЕА:

LD

A,#FF

LD

(#5D17),A

JP

#271B

#271 В:

LD

HL,#27FC

LD

A, #06

JP

# 1C4A

#1С4А:

CALL

#03C3

#ОЗСЗ:

PUSH

AF

LD

A,(#5D0E

;в эту ячейку ;перед запуском ;занесли #FE CP JR

;условие не выполняется

POP RET

AF

A,(#5CF8) #FF

Z,#211С

;условие не выполняется POP AF CALL #2970

#2970: PUSH HL PUSH DE PUSH ВС Как видим, здесь содержимое ВС (где находится столь нужный нам регистр состояния) заносится в стек. В моей процедуре этот факт используется для последующего восстановления ВС. PUSH AF LD HL,#5D0C ;в эту ячейку ; перед запуском ;занесли #FF LD A,(HL) OR A JR NZ,#2992 ;условие выполняется

#2992: POP AF POP ВС Содержимое ВС извлечено из стека, но в памяти, отведенной под стек, оно осталось. Его можно извлечь оттуда, лишь бы оно не было затерто записываемыми в стек значениями. Процедура обработки прерываний затрет значение ВС, а потому прерывания запрещены.

POP DE POP HL RET

#20E5: ;там 0

PUSH LD

CP JR

шшшшшшшш

форум

# 1C4D: JP #01D3

HL,0

(#5CF8),HL #20E5

#01D3:

LD LD

CALL

#20F1: PUSH LD

;в эту ячейку ;перед запуском

AF

А,(#5СВ6)

.занесли #F4 CP JR

#211С:

#01 DC: CALL

# 1D63:

;в эту ячейку ;перед запуском ;занесли #FE LD CP LD RET

#01DF: LD LD LD

;в эту ячейку {перед запуском {занесли #FF LD OR LD JR

#F4

Z,#211С

;условие выполняется

POP RET

AF

#1D63

LD

HL,#5D0E

A,(HL) #FF (HL).O NZ

{условие выполняется

HL,#5D17 (HL),#AA HL,#5D1 F

A,(HL) A

(HL),0 NZ,#01F3

{условие выполняется

#01F3: LD SP,(#5D1C) {значения этих ячеек

LD HL,(#5D1A) {подготовлены заранее

LD BC,(#5D0F) {теперь ВС осталось {только в стеке...

LD В,0 JP (HL)

При выходе управление передается на метку SSPEC, а SP указывает на то самое значение системного регистра, которое когда-то было сохранено в стеке.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Лит.страничка - Рассказ "Дятел".
Вступление - об авторах, содержание номера.
Toys - Новелла к игре "BISMARK".
Партийная зона - CC000 invitation dentro compo.
Приложение - Doxycon'99 - Invitation intro.

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