Page 1 of 1
Call gates
Posted: Sun May 09, 2004 12:51 pm
by ManOfSteel
Hello,
I'm very confused about call gates. I read somewhere (in 'Intel - System Programming', I think) that call gates are divided into trap gates and interrupt gates. Since call gates are found in the GDT and the two others in the IDT and that GDT has nothing to do with IDT, then, how can this be possible?
Besides, I didn't find any helpful description of a call gate. They can be used to call procedures (like the interrupts), right? How can I modify a normal GDT segment so it can become a call gate?
thanks for any help.
Re:Call gates
Posted: Sun May 09, 2004 1:49 pm
by Pype.Clicker
you do not modify a segment to become a gate: you define a gate that makes a user enter a segment.
You may think of gates as "redirectors". when one calls a gate, it actually get redirected towards what the gate defines.
Since gates provide all the information required to define an entry point, Intel designers found it smart to call the 'interrupt table' descriptors 'gates' aswell. Some gates make little sense out of the IDT (like the Interrupt gate, which is simply a trap that will clear the IF bit when entered and restore it when left, iirc)
Other kind of gates (notably the Task gate) may exist in both GDT, LDT and IDT.
Re:Call gates
Posted: Mon May 10, 2004 3:18 pm
by ManOfSteel
Hello,
is there anything wrong with this call gate?
Code: Select all
GDT:
;null segment
;code segment
;data segment
;video segment
CallGate01:
dw cg1 ;offset
dw 08h ;selector
db 0 ;
db 10001100b ;present (1), ring0 (00), type (01100)
dw 0 ;offset
GDTEnd:
cg1: ;call gate handler (does nothing)
iret
How do I call it? 'call 28h:0'?
Re:Call gates
Posted: Tue May 11, 2004 1:30 am
by Pype.Clicker
"call far 28h:0" could be preferred depending on your assembler. Note that a call gate does not return with "iret" but instead with "retf"
Re:Call gates
Posted: Tue May 11, 2004 1:40 am
by Brendan
Hi,
ManOfSteel wrote:Code: Select all
GDT:
;null segment
;code segment
;data segment
;video segment
CallGate01:
dw cg1 ;offset
dw 08h ;selector
db 0 ;
db 10001100b ;present (1), ring0 (00), type (01100)
dw 0 ;offset
GDTEnd:
cg1: ;call gate handler (does nothing)
iret
If the offset "cg1" is not within the first 64 Kb of memory it will be truncated (your assembler may/may not give a warning/error). If the call gate is to be used by CPL=3 code (a good assumption IMHO) then you'll want DPL=3. Also the code called by the call gate should use "RETF" to return rather than "IRETD".
Code: Select all
GDT:
;null segment 0x0000
;code segment 0x0008
;data segment 0x0010
;video segment 0x0018
CallGate01: ; 0x0020
dw (cg1 & 0xFFFF) ;offset low word
dw 08h ;selector
db 0 ;stack parameters to copy
db 11101100b ;present (1), DPL (03), type (01100)
dw (cg1 >> 16) ;offset high word
GDTEnd:
cg1: ;call gate handler (does nothing)
retf
How do I call it? 'call 28h:0'?
Yes, well almost - "call 20h:0"
Cheers,
Brendan
Re:Call gates
Posted: Thu May 13, 2004 1:22 am
by ManOfSteel
Hello and thanks for your replies, but after a lot of tries, my call gate is still not working. Bochs crashes (illegal opertion) before running any piece of code.
I used Bochs 1.4.1 and 2.1 and it is not working better with any one.
The illegal operation (with Bochs 1.4.1 only):
Code: Select all
BOCHS caused an invalid page fault in module BOCHS.EXE at 0187:0043d132.
Registers:
EAX=00bafd20 CS=0187 EIP=0043d132 EFLGS=00010246
EBX=00aa0000 SS=018f ESP=00bafc94 EBP=00bafcf8
ECX=549d01e5 DS=018f ESI=81766e60 FS=4ee7
EDX=00000000 ES=018f EDI=00000000 GS=0000
Bytes at CS:EIP:
8a 11 89 55 e8 8b 45 08 83 c0 01 89 45 08 8b 4d
Stack dump:
00bafca0 0046b739 00000020 00bafcb0 0046b20a 004adc60 00000000 00bafcc8 00401986 004adc60 00000002 00cd07f0 00000065 00bafce8 00401da3 00000019
Bochs 1.4.1 output:
Code: Select all
00000000000i[MEM0 ] 8.00MB
00000000000i[MEM0 ] rom at 0xf0000/65536 ('../BIOS-bochs-latest')
00000000000i[MEM0 ] rom at 0xc0000/32769 ('../VGABIOS-elpin-2.40')
00000000000i[CMOS ] Setting initial clock to: Thu May 13 09:53:15 2004
00000000000i[FDD ] fd0: '1.44' ro=0, h=2,t=80,spt=18
00000000000i[SB16 ] midi=0, wave=0, log=0, dmatimer=0
00000000000i[VGA ] interval=30000
00000000000i[VGA ] VBE Bochs Display Extension Enabled
00000000000i[KBD ] will paste characters every 1000 keyboard ticks
00000004012i[BIOS ] rombios.c,v 1.42.2.1 2002/05/15 13:41:03 cbothamy Exp $
00000006521i[VGA ] char map select: #1=0 / #2=0 (unused)
00000156932e[HD ] device set to 0 which does not exist
00000158492e[HD ] device set to 1 which does not exist
00000160052e[HD ] device set to 0 which does not exist
00000162496e[HD ] device set to 1 which does not exist
00000163456e[HD ] device set to 0 which does not exist
00000164493e[HD ] device set to 1 which does not exist
00000165092e[HD ] device set to 0 which does not exist
00000165696e[HD ] device set to 0 which does not exist
00000166896e[HD ] device set to 1 which does not exist
00000168115e[HD ] device set to 1 which does not exist
00000168717e[HD ] device set to 0 which does not exist
00000171200e[HD ] device set to 1 which does not exist
00000172160e[HD ] device set to 0 which does not exist
00000173197e[HD ] device set to 1 which does not exist
00000173796e[HD ] device set to 0 which does not exist
00000176592e[HD ] device set to 1 which does not exist
00000177552e[HD ] device set to 0 which does not exist
00000178589e[HD ] device set to 1 which does not exist
00000179188e[HD ] device set to 0 which does not exist
00000216075i[FDD ] partial read() on floppy image returns 328/512
00000217085e[CPU ] prefetch: running in bogus memory
Re:Call gates
Posted: Thu May 13, 2004 1:24 am
by ManOfSteel
My GDT, which contains the call gate, is directly followed by the call gate handler:
Code: Select all
GDTDESCR:
GDTLimit dw GDTEnd-GDT-1
GDTBase dd GDT
GDT:
GDTNull:
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
GDTCode:
db 0ffh
db 0ffh
db 00h
db 00h
db 00h
db 10011011b
db 11011111b
db 00h
GDTData:
db 0ffh
db 0ffh
db 00h
db 00h
db 00h
db 10010011b
db 11011111b
db 00h
GDTVideo:
db 9fh
db 0fh
db 00h
db 80h
db 0bh
db 92h
db 00h
db 00h
CallGate01:
dw cg1
dw 08h
db 0
db 10001100b
dw 0
GDTEnd:
cg1:
retf
I jump to the call gate like this:
Brendan, I didn't really understand what you meant by these:
Code: Select all
dw (cg1 & 0xFFFF) ;offset low word
...
dw (cg1 >> 16) ;offset high word
If the call gate is to be used by CPL=3 code (a good assumption IMHO) then you'll want DPL=3.
In fact, I'm using it with ring zero code. I will not use it only to jump to different-DPL-code but as interrupts (yeah, I know, I can do it with interrupt gates).
PS: sorry for pasting too much information here.
Re:Call gates
Posted: Thu May 13, 2004 3:04 am
by Pype.Clicker
ManOfSteel wrote:
Brendan, I didn't really understand what you meant by these:
Code: Select all
dw (cg1 & 0xFFFF) ;offset low word
...
dw (cg1 >> 16) ;offset high word
What brendan mean is that a 'dw' can only hold 16 bits of your potentially-32-bits offset (cg1). A 32 bits value can be split in two 16 bits values using
lo=full & 0xFFFF (masking out the higher bits) and
hi=full >> 16 (right-shifting the full value).
The problem is that, in most situations, such things doesn't work because the exact value of the symbol 'cg1' is unknown to the assembler (which must leave a part of the job to the linker) and that linkable objects usually cannot tell "this is the lowest 16 bits of a 32 bits offset, the highest 16 bits are there... look ..."
So you have to leave the two fields unfilled and perform the computations yourself at runtime, before you use the callgate (of course)
Re:Call gates
Posted: Fri May 14, 2004 4:04 am
by ManOfSteel
So you have to leave the two fields unfilled and perform the computations yourself at runtime, before you use the callgate (of course)
And how is that done? Is it possible to take the 32 bits offset and split it into two 16 bits offset? Can it be done using shr and shl or something else?
Re:Call gates
Posted: Fri May 14, 2004 4:22 am
by Brendan
Hi,
ManOfSteel wrote:
And how is that done? Is it possible to take the 32 bits offset and split it into two 16 bits offset? Can it be done using shr and shl or something else?
Yes:
Code: Select all
;Set kernel process call gate offset
mov ebx,[KERNspace+HEADEREND]
mov [GDTaddress+SELPROCAPI],bx
shr ebx,16
mov [GDTaddress+SELPROCAPI+6],bx
Cheers,
Brendan
Re:Call gates
Posted: Fri May 14, 2004 11:04 am
by ManOfSteel
What am I doing wrong again?
This is before setting up the GDT (lgdt)...
Code: Select all
mov ebx,[cg1]
mov [cg1low],bx
shr ebx,16
mov [cg1high],bx
...and This is my call gate
Code: Select all
CallGate01:
dw cg1low
dw 08h
db 0
db 10001100b
dw cg1high
GDTEnd:
cg1:
retf
cg1low dw 0
cg1high dw 0
Re:Call gates
Posted: Sat May 15, 2004 5:00 am
by Brendan
Hi,
ManOfSteel wrote:
What am I doing wrong again?
Try this:
Code: Select all
mov ebx,cg1
mov [CallGate01],bx
shr ebx,16
mov [CallGate01+6],bx
...and This is the call gate:
CallGate01:
dw 0 ;Offset low word (set dynamically)
dw 08h ;Code segment
db 0
db 11101100b ;present (1), ring3 (11), type (01100)
dw 0 ;Offset high word (set dynamically)
GDTEnd:
cg1:
retf
Hope that helps...
Cheers,
Brendan