Hello Peter ...
Monday December 08, you wrote to Marius Bendiksen
MB>> * The realmode IDT is stuck (usually) at 0:0 with a limit of
MB>> 0x3ff
PL> "Usually" ?
Yep...
=== Cut ===
; Rene Herman, public domain, tasm lidt, tlink lidt, *will* set fire to
; your computer.
;
; Example showing validity of LIDT in real mode. Just like in protected
; mode, the real mode interrupt "descriptor" (vector) table can reside
; anywhere in the CPUs address space (that's 1MB+64k-16 in real mode),
; including the HMA (addresses 100000-10FFEF, as long as A20 is enabled,
; naturally).
;
; Although the base field of LIDT's operand is a 24bit (or 32bit, with
; an operand size prefix on a 386+) physical address, it seems it isn't
; possible to place the IDT in extended memory. The operand does get
; accepted, but the machine crashes on the first interrupt.
;
; SIDT is a non-priviliged instruction and will (therefore) return the
; protected mode IDTR when called from v86 mode. LIDT is privileged,
; so a v86 monitor may or may not emulate it (EMM386 from PC-DOS 7
; doesn't) making this stuf usefull only in "real" real mode (useless,
; that is).
_TEXT SEGMENT PARA STACK
@NULL LABEL
ASSUME CS:_TEXT, DS:_TEXT
Msg DW MsgNope
Msg286 DB 'This program requires a 286+$'
MsgReal DB 'This program requires real mode$'
MsgNope DB 'Nope, didn''t do anything$'
MsgOkay DB 'Seems to work okay$'
MsgCrLf DB 13, 10, '$'
; The new int 0 handler, residing (only) in the relocated IDT. Simply sets
; message to the "okay msg", showing that it got executed.
NewInt0 PROC
mov cs:[Msg], OFFSET MsgOkay
iret
NewInt0 ENDP
main PROC ; program entry point
push cs
pop ds
mov dx, OFFSET MsgCrLf
mov ah, 009h
int 021h
; 286 detection routine.
mov dx, OFFSET Msg286
pushf ; save flags
pushf ; get flags
pop ax
and ax, 00FFFh ; clear bits 12 to 15
push ax ; set flags
popf
pushf ; get flags
pop ax
popf ; restore flags
cmp ax, 0F000h ; bits 12 to 15 set?
je @@Exit ; > y (not a 286+)
.286P ; TASM insists on the 'P'
mov dx, OFFSET MsgReal
smsw ax ; smsw can't be trapped
shr ax, 1 ; real mode?
jc @@Exit ; > n
sidt [OldIDTR] ; store IDTR into OldIDTR
; Calculate physical address for new one-vector IDT
mov ax, ds
rol ax, 4
mov dx, ax
and ax, 0FFF0h
and dx, 00Fh
add WORD PTR [NewIDTR.Base], ax
adc WORD PTR [NewIDTR.Base + WORD], dx
cli ; disable interrupts
mov al, 080h ; disable NMI
out 070h, al
lidt [NewIDTR] ; load the new IDTR
int 0
lidt [OldIDTR] ; restore old IDTR
xor al, al
out 070h, al ; enable NMI
sti ; enable interrupts
mov dx, [Msg]
@@Exit:
mov ah, 009h
int 021h
mov dx, OFFSET MsgCrLf
int 021h
mov ax, 04C00h
int 021h
main ENDP
; New interrupt vector table starts here. It seems that any byte adress in
; the "1MB+64K-16 - 4 * (highest interrupt number used + 1)" range will do
; as IDT base, although dword alignment will no doubt speed up table access.
Int0 DD NewInt0
; LIDT/SIDT load/store from/to a 6 byte memory operand formated as:
IDTR STRUC
Limit DW ?
Base DD ?
IDTR ENDS
; The " - @NULL" just to get TASM to place a 16bit offset into a dword
NewIDTR IDTR { Limit = 00003h, Base = Int0 - @NULL }
OldIDTR IDTR ?
DW 00200h DUP (?) ; stack
_TEXT ENDS
END main
=== Cut ===
Rene
---
---------------
* Origin: rene.herman@tip.nl (2:282/1.11)
|