- Статьи для начинающих -

   
- Назад на оглавление -
Включение A20 с подробными комментариями

;;
;; enableA20.s (adapted from Visopsys OS-loader)
;;
;; Copyright (c) 2000, J. Andrew McLaughlin
;; You're free to use this code in any manner you like, as long as this
;; notice is included (and you give credit where it is due), and as long
;; as you understand and accept that it comes with NO WARRANTY OF ANY KIND.
;; Contact me at jamesamc@yahoo.com about any bugs or problems.
;;

enableA20:
;; Эта процедура включит A20 через контроллер клавиатуры
;; Аргументы: нет.  Возвращает: 0 в EAX в случае успеха,
;; -1 при ошибке.  Написано для использования в 16-битном коде
;; (32-битные участки помечены как 32-BIT)

pusha

;; Убедимся, что прерывания отключены
cli

;; В CX будет счетчик (мы предпримем до 5 попыток включения A20)
mov CX, 5

.startAttempt1:
;; Подождем пока контроллер готов принимать команды
.commandWait1:
xor AX, AX
in AL, 64h
bt AX, 1
jc .commandWait1

;; Скажем контроллеру, что мы хотим прочитать текущий статус
;; (команда D0h)
mov AL, 0D0h
out 64h, AL

;; Подождем пока контроллер готов
.dataWait1:
xor AX, AX
in AL, 64h
bt AX, 0
jnc .dataWait1

;; Прочитаем текущий статус из порта 60h
xor AX, AX
in AL, 60h

;; сохраним текущее значение (E)AX
push AX; 16-BIT
;; push EAX; 32-BIT

;; Подождем пока контроллер готов
.commandWait2:
in AL, 64h
bt AX, 1
jc .commandWait2

;; Скажем контроллер, что мы снова хотим записать байт статуса
mov AL, 0D1h
out 64h, AL

;; Подождем пока контроллер готов
.commandWait3:
xor AX, AX
in AL, 64h
bt AX, 1
jc .commandWait3

;; Запишем новое значение в порт 60h.  Напоминаю, что предыдущее
;; мы сохранили в стеке
pop AX; 16-BIT
;; pop EAX; 32-BIT

;; Установим бит включения A20
or AL, 00000010b
out 60h, AL

;; И, наконец, прочитаем байт статуса, чтобы убедиться
;; что A20 был включен

;; Подождем пока контроллер готов
.commandWait4:
xor AX, AX
in AL, 64h
bt AX, 1
jc .commandWait4

;; Команда D0h
mov AL, 0D0h
out 64h, AL

;; Подождем пока контроллер готов
.dataWait2:
xor AX, AX
in AL, 64h
bt AX, 0
jnc .dataWait2

;; Прочитаем статус из порта 60h
xor AX, AX
in AL, 60h

;; Шлюз A20 включен?
bt AX, 1

;; Проверим результат.  Если флаг CF установлен, то A20 включен.
jc .success

;; Повторить операцию?  Если счетчик в ECX
;; не дошел до нуля, мы должны повторить
loop .startAttempt1


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


;; Счетчик попыток
mov CX, 5

.startAttempt2:
;; Подождем пока контроллер готов
.commandWait6:
xor AX, AX
in AL, 64h
bt AX, 1
jc .commandWait6

;; Скажем контроллеру, что мы хотим включить A20
mov AL, 0DFh
out 64h, AL

;; Прочитаем статус A20, чтобы убедиться, что A20 включен

;; Подождем пока контроллер готов
.commandWait7:
xor AX, AX
in AL, 64h
bt AX, 1
jc .commandWait7

;; Команда D0h.
mov AL, 0D0h
out 64h, AL

;; Подождем пока контроллер готов
.dataWait3:
xor AX, AX
in AL, 64h
bt AX, 0
jnc .dataWait3

;; Прочитаем байт статуса из порта 60h
xor AX, AX
in AL, 60h

;; A20 включен?
bt AX, 1

;; Проверим CF. Если он установлен, то A20 включен.
;; Предупредим, что пришлось использовать альтернативный метод
jc .warn

;; Повторим операцию, если CX не дошел до нуля
loop .startAttempt2


;; Мда, у нас ничего не получилось. Здесь можно поместить
;; сообщение об ошибке
jmp .fail


.warn:
;; Здесь можно поместить сообщение о том, что пришлось
;; использовать альтернативный метод включения A20

.success:
sti
popa
xor EAX, EAX
ret

.fail:
sti
popa
mov EAX, -1
ret
Хостинг от uCoz