Page 1 of 2
How to access BIOS Interrupt without using "INT" instuction
Posted: Thu Mar 17, 2011 4:12 am
by osdevkid
Dear All,
I wonder the below code access BIOS interrupt 0x41 and loads the FDPT address (Address pointer: FDPT = Fixed Disk Parameter Table (1st hard drive)) in to SI register and transfer the 16 bytes in to address 0x90080.
Code: Select all
; Get hd0 parameter table info pointed at by BIOS int 0x41
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41] ; set DS:[SI]
mov ax,#0x9000
mov es,ax
mov di,#0x0080 ; ES:[DI] = 0x90080
mov cx,#0x10 ; repeat 16 times
rep
movsb ; copy byte at DS:[SI] to ES:[DI] & update SI and DI.
I know, each BIOS interrupt vector is 4 bytes long, but I want to know, how this calculation [4 * 0x41] works ?
First I have assumed as, it is a simple index calculation method, however the BIOS interrupts are start from 00h to 1Fh and 41h, 46h, 4Ah, etc., so the list is not in constant incremental order, so I got confused.
Dear experts please clarify me,
1) how it is working ([4 * 0x41])?
2) In this case, is it possible to access all BIOS interrupts in the same manner without calling "INT" instruction?
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 17, 2011 4:30 am
by bluemoon
The IVT is layout such that the first 1024 byte of memory corresponding to the address of 256 vectors, each 4 bytes in size.
So, the address of 0x41-th vector will be (0x41 * 4).
It's worth noticing that lds si, [0x41*4] actually load data from DS:[0x41*4], that's why it is needed to be cleared to zero.
For the second question, yes, you can access(read/write) them using similar manner, you may also simulate INT instruction to execute them with push/jumps, which is fairly common technique to hook/replace an interrupt vector.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 17, 2011 4:45 am
by osdevkid
bluemoon wrote:So, the address of 0x41-th vector will be (0x41 * 4).
It's worth noticing that lds si, [0x41*4] actually load data from DS:[0x41*4], that's why it is needed to be cleared to zero.
Hai bluemoon,
Thanks for your reply, what you would like to explain to me is, BIOS interrupts list is in incremental order like below:
Code: Select all
00h to 1Fh
20h to 40h => reserved
41h
42h to 45h => reserved
46h
etc.,
So we can acces like an array, am I right ? please confirm.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 17, 2011 5:34 am
by jal
osdevkid wrote:So we can acces like an array, am I right ? please confirm.
You should Google the term "IVT" and it will explain all. It seems that you don't have the
required knowledge.
JAL
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 17, 2011 6:47 am
by Tosi
Also look in the intel manuals for where it explains the operation of real mode interrupts. It's somewhere in the second volume.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Mon Mar 21, 2011 7:43 am
by trinopoty
Each entry in the IVT is 4 bytes structured as follows:
Code: Select all
struct IVT_Entry
{
unsigned short offset;
unsigned short segment;
};
So if you want ot call BIOS interrupts without the INT instruction; do as follows:
Code: Select all
mov ax, 0x0000
mov ds, ax
mov ax, 0x41 ; interrupt no
mov cx, 0x04
xor dx, dx
mul cx
mov bx, ax
les ax ds:[bx] ; ES = interrupt segment; AX = interrupt offset
push 0x0000 ; replace 0x0000 with the segment where the interrupt will return
push 0x0000 ; replace 0x0000 with the offset where the interrupt will return
push es
push ax
retf ; calls the interupt
But its a lot faster to use the INT instruction.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Wed Mar 23, 2011 7:18 am
by turdus
trinopoty wrote:
So if you want ot call BIOS interrupts without the INT instruction; do as follows:
Code: Select all
mov ax, 0x0000
mov ds, ax
mov ax, 0x41 ; interrupt no
mov cx, 0x04
xor dx, dx
mul cx
mov bx, ax
les ax ds:[bx] ; ES = interrupt segment; AX = interrupt offset
push 0x0000 ; replace 0x0000 with the segment where the interrupt will return
push 0x0000 ; replace 0x0000 with the offset where the interrupt will return
push es
push ax
retf ; calls the interupt
But its a lot faster to use the INT instruction.
Your code is messy. You can do the same with less code:
Code: Select all
xor ax, ax
mov es, ax
mov bl, 0x41 ;interrupt number
shl bx, 2
les ax, ds:[bx]
pushf
call far es:ax
But, this is not the case here. The point is that the specified ISR address does not hold an executable code, so you can't call it, instead it's a data area that has to be read (using "mov" instead of "call"/"int").
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Wed Mar 23, 2011 7:51 am
by qw
I edited this reply so many times it became a bit messy. And in the mean time, Turdus already replied. So I deleted the whole thing.
Last note: "call far es:ax" is illegal. Make it "call far [es:bx]".
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Wed Mar 23, 2011 7:53 am
by turdus
Hobbes wrote:There is no [AX].
The routine will return with an IRET so you have to push the flags too.
Right! My mistake.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 24, 2011 3:50 am
by ym
turdus wrote:trinopoty wrote:
So if you want ot call BIOS interrupts without the INT instruction; do as follows:
Code: Select all
mov ax, 0x0000
mov ds, ax
mov ax, 0x41 ; interrupt no
mov cx, 0x04
xor dx, dx
mul cx
mov bx, ax
les ax ds:[bx] ; ES = interrupt segment; AX = interrupt offset
push 0x0000 ; replace 0x0000 with the segment where the interrupt will return
push 0x0000 ; replace 0x0000 with the offset where the interrupt will return
push es
push ax
retf ; calls the interupt
But its a lot faster to use the INT instruction.
Your code is messy. You can do the same with less code:
Code: Select all
xor ax, ax
mov es, ax
mov bl, 0x41 ;interrupt number
shl bx, 2
les ax, ds:[bx]
pushf
call far es:ax
But, this is not the case here. The point is that the specified ISR address does not hold an executable code, so you can't call it, instead it's a data area that has to be read (using "mov" instead of "call"/"int").
should these code work under protected mode ?
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 24, 2011 5:28 am
by eddyb
ym wrote:turdus wrote:trinopoty wrote:
So if you want ot call BIOS interrupts without the INT instruction; do as follows:
Code: Select all
mov ax, 0x0000
mov ds, ax
mov ax, 0x41 ; interrupt no
mov cx, 0x04
xor dx, dx
mul cx
mov bx, ax
les ax ds:[bx] ; ES = interrupt segment; AX = interrupt offset
push 0x0000 ; replace 0x0000 with the segment where the interrupt will return
push 0x0000 ; replace 0x0000 with the offset where the interrupt will return
push es
push ax
retf ; calls the interupt
But its a lot faster to use the INT instruction.
Your code is messy. You can do the same with less code:
Code: Select all
xor ax, ax
mov es, ax
mov bl, 0x41 ;interrupt number
shl bx, 2
les ax, ds:[bx]
pushf
call far es:ax
But, this is not the case here. The point is that the specified ISR address does not hold an executable code, so you can't call it, instead it's a data area that has to be read (using "mov" instead of "call"/"int").
should these code work under protected mode ?
You would need some kind of unreal mode for that.
Or if you don't want that, use an emulator to execute the real-mode code of the BIOS while remaining in protected mode.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Mar 24, 2011 6:23 am
by turdus
ym wrote:
should these code work under protected mode ?
That depends. Reading the pointed memory can be done without problem, but if you mean executing the pointed real mode ISR code the answer is no.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Apr 28, 2011 1:30 pm
by mxandmx
Turdus:
If you had everything running in ring 0 wouldn't you be able to execute the ISR? IS it due to the fact you'd be dealing with 32 bit registers? What about 16-bit protected mode then?
Cheers
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Thu Apr 28, 2011 3:03 pm
by Combuster
You can not execute real mode code in protected mode for the sole reason that the address translation scheme is incompatible.
Re: How to access BIOS Interrupt without using "INT" instuct
Posted: Tue May 03, 2011 3:22 am
by jal
Combuster wrote:You can not execute real mode code in protected mode for the sole reason that the address translation scheme is incompatible.
You cannot execute random real mode code in protected mode, that's for sure, but specially crafted code can run fine. I recall a story about the history of QNX, where the first x86 versions ran in real mode, each program/process limited to a 64KB page, and they had very little compatability problems when they introduced the 286 protected mode version, most programs running fine in PM as well.
JAL