Ответ
Биос в основном состоит из одного большого файла,
30 Янв 2004 - 14:31 Unknown BIOS
Ответ
Биос в основном состоит из одного большого файла, который ложится на два сегмента E000 и F000. Для того, чтобы вызвать подпрограмму, находящуюся в сегменте F000 (у нас $F) и имеющую инструкцию ближнего возврата, из сегмента E000 (у нас обозначено $E), используют подобный способ. Для этого необходимо в сегменте $F добавить две инструкции ближнего и дальнего возврата.
В подпрограмме $E_rtc_read_cmos после дальнего перехода на вершине стека остается адрес процедуры rtc_read_cmos, расположенной в $F. Переход осуществляется с помощью retn в сегменте $F. После ближнего выхода из подпрограммы rtc_read_cmos происходит переход на инструкцию retf, адрес которой оказывается на вершине стека в rtc_read_cmos. Тогда происходит дальний возврат на адрес $E@@ret.
В самом деле, различаться будут только второй и четвертый push, поскольку в них содержится информация о ближнем адресе вызова и адресе возврата. Сегмент $E и ближний адрес retf в сегменте $F - постоянные величины.
Этот пример можно найти везде, поскольку все приведенные адреса являются стандартными для всех биосов AWARD. Потому, имея любой подобный биос и зная адреса, такой листинг можно получить за минуту. У меня получилось немного громоздко, но, надеюсь, понятно.
Наш пример также показывает то, что биосы AWARD собираются из частей, написанных еще в 1992-1993 годах. Подобного рода задержки после вывода в порт будут работать на машинах не старше 486, а выравнивания на 4 перед инструкциями in и out также излишни.
$E segment
...
; ----------------------------------------------------------------------------
; $E8B15
$E_rtc_read_cmos proc near
push seg $E
push offset @@ret
push offset $F_retf
push offset rtc_read_cmos
jmp far ptr $F_retn
@@ret
ret
$E_rtc_read_cmos endp
; ----------------------------------------------------------------------------
; $E8B27
$E_rtc_write_cmos proc near
push seg $E
push offset @@ret
push offset $F_retf
push offset rtc_write_cmos
jmp far ptr $F_retn
@@ret
ret
$E_rtc_write_cmos endp
...
$E ends
$F segment
...
; ----------------------------------------------------------------------------
; $FE50C ; cmos[al] <= cmos[al] and ah
rtc_and_cmos proc near
mov bl, al
align 4
out 70h, al
jcxz $+2
align 4
in al, 71h
jcxz $+2
and ah, al
mov al, bl
align 4
out 70h, al
jcxz $+2
xchg al, ah
align 4
out 71h, al
jcxz $+2
ret
rtc_and_cmos endp
; ----------------------------------------------------------------------------
; $FE529 ; cmos[al] <= cmos[al] or ah
rtc_or_cmos proc near
mov bl, al
align 4
out 70h, al
jcxz $+2
align 4
in al, 71h
jcxz $+2
or ah, al
mov al, bl
align 4
out 70h, al
jcxz $+2
xchg al, ah
align 4
out 71h, al
jcxz $+2
ret
rtc_or_cmos endp
; ----------------------------------------------------------------------------
; $FE545 ; al <= cmos[al]
rtc_read_cmos proc near
align 4
out 70h, al
jcxz $+2
jcxz $+2
align 4
in al, 71h
jcxz $+2
jcxz $+2
ret
rtc_read_cmos endp
; ----------------------------------------------------------------------------
; $FE557 ; cmos[al] <= ah
rtc_write_cmos proc near
align 4
out 70h, al
jcxz $+2
jcxz $+2
xchg al, ah
align 4
out 71h, al
jcxz $+2
jcxz $+2
ret
rtc_write_cmos endp
Ответ
Биос в основном состоит из одного большого файла, который ложится на два сегмента E000 и F000. Для того, чтобы вызвать подпрограмму, находящуюся в сегменте F000 (у нас $F) и имеющую инструкцию ближнего возврата, из сегмента E000 (у нас обозначено $E), используют подобный способ. Для этого необходимо в сегменте $F добавить две инструкции ближнего и дальнего возврата.
В подпрограмме $E_rtc_read_cmos после дальнего перехода на вершине стека остается адрес процедуры rtc_read_cmos, расположенной в $F. Переход осуществляется с помощью retn в сегменте $F. После ближнего выхода из подпрограммы rtc_read_cmos происходит переход на инструкцию retf, адрес которой оказывается на вершине стека в rtc_read_cmos. Тогда происходит дальний возврат на адрес $E@@ret.
В самом деле, различаться будут только второй и четвертый push, поскольку в них содержится информация о ближнем адресе вызова и адресе возврата. Сегмент $E и ближний адрес retf в сегменте $F - постоянные величины.
Этот пример можно найти везде, поскольку все приведенные адреса являются стандартными для всех биосов AWARD. Потому, имея любой подобный биос и зная адреса, такой листинг можно получить за минуту. У меня получилось немного громоздко, но, надеюсь, понятно.
Наш пример также показывает то, что биосы AWARD собираются из частей, написанных еще в 1992-1993 годах. Подобного рода задержки после вывода в порт будут работать на машинах не старше 486, а выравнивания на 4 перед инструкциями in и out также излишни.
$E segment
...
; ----------------------------------------------------------------------------
; $E8B15
$E_rtc_read_cmos proc near
push seg $E
push offset @@ret
push offset $F_retf
push offset rtc_read_cmos
jmp far ptr $F_retn
@@ret
ret
$E_rtc_read_cmos endp
; ----------------------------------------------------------------------------
; $E8B27
$E_rtc_write_cmos proc near
push seg $E
push offset @@ret
push offset $F_retf
push offset rtc_write_cmos
jmp far ptr $F_retn
@@ret
ret
$E_rtc_write_cmos endp
...
$E ends
$F segment
...
; ----------------------------------------------------------------------------
; $FE50C ; cmos[al] <= cmos[al] and ah
rtc_and_cmos proc near
mov bl, al
align 4
out 70h, al
jcxz $+2
align 4
in al, 71h
jcxz $+2
and ah, al
mov al, bl
align 4
out 70h, al
jcxz $+2
xchg al, ah
align 4
out 71h, al
jcxz $+2
ret
rtc_and_cmos endp
; ----------------------------------------------------------------------------
; $FE529 ; cmos[al] <= cmos[al] or ah
rtc_or_cmos proc near
mov bl, al
align 4
out 70h, al
jcxz $+2
align 4
in al, 71h
jcxz $+2
or ah, al
mov al, bl
align 4
out 70h, al
jcxz $+2
xchg al, ah
align 4
out 71h, al
jcxz $+2
ret
rtc_or_cmos endp
; ----------------------------------------------------------------------------
; $FE545 ; al <= cmos[al]
rtc_read_cmos proc near
align 4
out 70h, al
jcxz $+2
jcxz $+2
align 4
in al, 71h
jcxz $+2
jcxz $+2
ret
rtc_read_cmos endp
; ----------------------------------------------------------------------------
; $FE557 ; cmos[al] <= ah
rtc_write_cmos proc near
align 4
out 70h, al
jcxz $+2
jcxz $+2
xchg al, ah
align 4
out 71h, al
jcxz $+2
jcxz $+2
ret
rtc_write_cmos endp
...
; ----------------------------------------------------------------------------
; $FEC30
$F_retn
retn
; ----------------------------------------------------------------------------
; $FEC31
$F_retf
retf
...
$F ends