simple asm protected mode switch help!
Posted: Wed May 11, 2005 4:17 pm
Hi all,
well I've been fiddling around with some asm code, trying to go into protected mode...I wanted to go into 32bit pm from dos instead of doing a boot disk...just simple stuff.
I've been messing around with this for ages...I mean its not long...kept it very simple...but I know its something to do with where the code is in memory or something stupid.
Its not much code...and when we get into pm it just seems to reboot the computer...tried all sorts of hacks and checks but think it has something to do with where the code is put in memory...or possibly offsets or something.
Thanks for any feedback on this :)
Ben
<div class='indent'>
; Run in dos (not under windows) and it will take us to 32 bit protected mode
[ORG 0x100] ; Reserve 256 bytes for dos
[BITS 16] ; Dos is 16 bits
; assemble using 'nasm' assembler
; C:>nasm asmtest.asm -o test.exe
jmp entry ; Jump to the start of our code
msg1 db 'Where good to go..$';
entry:
; Display a message showing where alive!
mov dx, msg1 ; register dx=msg1
mov ah, 9 ; register ah=9 -- the print string function
int 21h ; dos service interrupt .. looks at register ah to figure out what to do
; Where in dos, and we've done a simple text message to the screen to show
; our program is running... so now where going to break out of this real 16 bit
; world and get into 32 protected mode. So lets set things up and go go go..
cli ; Clear or disable interrupts
lgdt[gdtr] ; Load GDT
mov eax,cr0 ; The lsb of cr0 is the protected mode bit
or al,0x01 ; Set protected mode bit
mov cr0,eax ; Mov modified word to the control register
jmp go_pm
; Once we reach here where in protected mode! 32 Bit! Where not in
; the real world (mode) anymore :)
[BITS 32]
go_pm :
mov ax, 0; ; Just poke something into the graphics memory so that we
mov es, ax; ; know its all okay! *SEEMS TO CRASH HERE!!!*
mov word [es: 0xb8000],0x740
spin : jmp spin ; Loop forever
; We use 16 bit alignment here - as you'll notice we use dw and dd only,
; and out data will be packed together nice and tight.
[BITS 16]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Our GDTR register value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr :
dw gdt_end-gdt-1 ; Length of the gdt
dd gdt ; physical address of gdt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is the start of our gdt - its actual value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt:
nullsel equ $-gdt
gdt0
dd 0
dd 0
codesel equ $-gdt
code_gdt:
dw 0x0ffff
dw 0x0000
db 0x00
db 0x09a
db 0x0cf
db 0x00
datasel equ $-gdt
data_gdt:
dw 0x0ffff ; Limit 4Gb
dw 0x0000 ; Base 0000:0000h
db 0x00 ; Descriptor format same as above
db 0x092
db 0x0cf
db 0x00
gdt_end:
TIMES 0x500-($-$$) DB 0x90 ; And of course, this will make our file size
; equal to 0x500 a nice round number -
; 0x500 ... so if you assemble the file
; you should find its that size exactly.
</div>
well I've been fiddling around with some asm code, trying to go into protected mode...I wanted to go into 32bit pm from dos instead of doing a boot disk...just simple stuff.
I've been messing around with this for ages...I mean its not long...kept it very simple...but I know its something to do with where the code is in memory or something stupid.
Its not much code...and when we get into pm it just seems to reboot the computer...tried all sorts of hacks and checks but think it has something to do with where the code is put in memory...or possibly offsets or something.
Thanks for any feedback on this :)
Ben
<div class='indent'>
; Run in dos (not under windows) and it will take us to 32 bit protected mode
[ORG 0x100] ; Reserve 256 bytes for dos
[BITS 16] ; Dos is 16 bits
; assemble using 'nasm' assembler
; C:>nasm asmtest.asm -o test.exe
jmp entry ; Jump to the start of our code
msg1 db 'Where good to go..$';
entry:
; Display a message showing where alive!
mov dx, msg1 ; register dx=msg1
mov ah, 9 ; register ah=9 -- the print string function
int 21h ; dos service interrupt .. looks at register ah to figure out what to do
; Where in dos, and we've done a simple text message to the screen to show
; our program is running... so now where going to break out of this real 16 bit
; world and get into 32 protected mode. So lets set things up and go go go..
cli ; Clear or disable interrupts
lgdt[gdtr] ; Load GDT
mov eax,cr0 ; The lsb of cr0 is the protected mode bit
or al,0x01 ; Set protected mode bit
mov cr0,eax ; Mov modified word to the control register
jmp go_pm
; Once we reach here where in protected mode! 32 Bit! Where not in
; the real world (mode) anymore :)
[BITS 32]
go_pm :
mov ax, 0; ; Just poke something into the graphics memory so that we
mov es, ax; ; know its all okay! *SEEMS TO CRASH HERE!!!*
mov word [es: 0xb8000],0x740
spin : jmp spin ; Loop forever
; We use 16 bit alignment here - as you'll notice we use dw and dd only,
; and out data will be packed together nice and tight.
[BITS 16]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Our GDTR register value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr :
dw gdt_end-gdt-1 ; Length of the gdt
dd gdt ; physical address of gdt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is the start of our gdt - its actual value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt:
nullsel equ $-gdt
gdt0
dd 0
dd 0
codesel equ $-gdt
code_gdt:
dw 0x0ffff
dw 0x0000
db 0x00
db 0x09a
db 0x0cf
db 0x00
datasel equ $-gdt
data_gdt:
dw 0x0ffff ; Limit 4Gb
dw 0x0000 ; Base 0000:0000h
db 0x00 ; Descriptor format same as above
db 0x092
db 0x0cf
db 0x00
gdt_end:
TIMES 0x500-($-$$) DB 0x90 ; And of course, this will make our file size
; equal to 0x500 a nice round number -
; 0x500 ... so if you assemble the file
; you should find its that size exactly.
</div>