P-Mode code fails on jmp
Posted: Sun Feb 03, 2002 12:00 am
The p-mode code im working with dies in bochs when the first jmp (jmp SYS_CODE_SEL:do_pm )is called after i get into p-mode. Bochs returns with an error
s=1 descriptor not executable. From what I can figure everything is
ok and the descriptor im trying to work with (SYS_CODE_SEL) is
executable and should work fine. Here’s a copy of the code
if anyone has any ideas on what could be going wrong
I would really appreciate the help.
[BITS 16]
[ORG 0]
jmp short Start
nop
Start:
cli ; disable interrupts
xor ebx,ebx ; now in real mode (16-bit)
mov bx,cs
shl ebx,4
mov eax,ebx ; EAX=EBX=CS<<4
lea eax,[ebx]
mov [gdt2 + 2],ax ; set descriptor base address=EAX
mov [gdt3 + 2],ax
shr eax,16
mov [gdt2 + 4],al
mov [gdt3 + 4],al
mov [gdt2 + 7],ah
mov [gdt3 + 7],ah
lea eax,[ebx + gdt] ; point gdt_ptr to the gdt
mov [gdt_ptr + 2],eax ; EAX=linear address of gdt
push dword 0 ; zero EFLAGS (interrupts off,
popfd ; IOPL=0, NT bit=0)
lgdt [gdt_ptr]
mov eax,cr0
or al,1
mov cr0,eax
jmp SYS_CODE_SEL:do_pm
do_pm:
mov ax,SYS_DATA_SEL ; now in 32-bit pmode
mov ds,eax ; EAX works, one byte smaller
mov ss,eax
nop
mov es,eax
mov fs,eax
mov gs,eax
xor eax,eax ; zero top 16 bits of ESP
mov ax,sp
mov esp,eax
jmp $ ; loop
;*******
; Data *******************************************************
;*******
; null descriptor
gdt: dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-gdt
dw 0xFFFF ; limit 0xFFFFF (1 meg? 4 gig?)
dw 0 ; base for this one is always 0
db 0
db 0x92 ; present,ring 0,data,expand-up,writable
db 0xCF ; page-granular (4 gig limit), 32-bit
db 0
; code segment descriptor
SYS_CODE_SEL equ $-gdt
gdt2: dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x9A ; present,ring 0,code,non-conforming,readable
db 0xCF
db 0
; data segment descriptor
SYS_DATA_SEL equ $-gdt
gdt3: dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x92 ; present,ring 0,data,expand-up,writable
db 0xCF
db 0
gdt_end:
gdt_ptr:
dw gdt_end - gdt - 1 ; GDT limit
dd gdt ; linear, physical address of GDT
times 510-($-$$) db 0 ; pad the file with the needed 0 bytes to
; make it 510 bytes at this point
dw 0xAA55 ; boot sector signature needed to have
; bios read it as a bootsector
s=1 descriptor not executable. From what I can figure everything is
ok and the descriptor im trying to work with (SYS_CODE_SEL) is
executable and should work fine. Here’s a copy of the code
if anyone has any ideas on what could be going wrong
I would really appreciate the help.
[BITS 16]
[ORG 0]
jmp short Start
nop
Start:
cli ; disable interrupts
xor ebx,ebx ; now in real mode (16-bit)
mov bx,cs
shl ebx,4
mov eax,ebx ; EAX=EBX=CS<<4
lea eax,[ebx]
mov [gdt2 + 2],ax ; set descriptor base address=EAX
mov [gdt3 + 2],ax
shr eax,16
mov [gdt2 + 4],al
mov [gdt3 + 4],al
mov [gdt2 + 7],ah
mov [gdt3 + 7],ah
lea eax,[ebx + gdt] ; point gdt_ptr to the gdt
mov [gdt_ptr + 2],eax ; EAX=linear address of gdt
push dword 0 ; zero EFLAGS (interrupts off,
popfd ; IOPL=0, NT bit=0)
lgdt [gdt_ptr]
mov eax,cr0
or al,1
mov cr0,eax
jmp SYS_CODE_SEL:do_pm
do_pm:
mov ax,SYS_DATA_SEL ; now in 32-bit pmode
mov ds,eax ; EAX works, one byte smaller
mov ss,eax
nop
mov es,eax
mov fs,eax
mov gs,eax
xor eax,eax ; zero top 16 bits of ESP
mov ax,sp
mov esp,eax
jmp $ ; loop
;*******
; Data *******************************************************
;*******
; null descriptor
gdt: dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-gdt
dw 0xFFFF ; limit 0xFFFFF (1 meg? 4 gig?)
dw 0 ; base for this one is always 0
db 0
db 0x92 ; present,ring 0,data,expand-up,writable
db 0xCF ; page-granular (4 gig limit), 32-bit
db 0
; code segment descriptor
SYS_CODE_SEL equ $-gdt
gdt2: dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x9A ; present,ring 0,code,non-conforming,readable
db 0xCF
db 0
; data segment descriptor
SYS_DATA_SEL equ $-gdt
gdt3: dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x92 ; present,ring 0,data,expand-up,writable
db 0xCF
db 0
gdt_end:
gdt_ptr:
dw gdt_end - gdt - 1 ; GDT limit
dd gdt ; linear, physical address of GDT
times 510-($-$$) db 0 ; pad the file with the needed 0 bytes to
; make it 510 bytes at this point
dw 0xAA55 ; boot sector signature needed to have
; bios read it as a bootsector