Switching to Protected mode with gnu as
Posted: Tue Nov 08, 2022 4:01 am
I am forcing myself to try to use `ld` and `as` as built by binutils and not use nasm. This worked fine while in real mode, but now that I am trying to enter protected mode I am encountering issues. The main problem is I can't get `as` to compile the same way that nasm does.
The minimum example I could find is a nasm bootsector I copied from http://3zanders.co.uk/2017/10/13/writin ... /boot2.asm.
When I convert this to att syntax and gnu assembler directives (and using -Ttext 0x7c00 with my linker command to do the equivalent of [org])
However these produce very different assembly code:
The main difference between the two codes is that for gnu as, I had to relocate the gdt to be above the boot function which means I also had to add a jmp at the beginning of the code and add a label to ensure that at the end we are the right number of bytes.
If I try to put the gdt in the same spot as nasm, the long jump gives me an error: Error: can't handle non absolute segment in `jmp'.
I'm trying really hard (for no particular reason) to avoid using nasm and only use gnu gcc tools, but I'm getting stuck on switching to protected mode.
Any thoughts/suggestions?
The minimum example I could find is a nasm bootsector I copied from http://3zanders.co.uk/2017/10/13/writin ... /boot2.asm.
Code: Select all
bits 16
org 0x7c00
boot:
mov ax, 0x2401
int 0x15
mov ax, 0x3
int 0x10
cli
lgdt [gdt_pointer]
mov eax, cr0
or eax,0x1
mov cr0, eax
jmp CODE_SEG:boot2
nop
gdt_start:
dq 0x0
gdt_code:
dw 0xFFFF
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
gdt_data:
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end:
gdt_pointer:
dw gdt_end - gdt_start
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
bits 32
boot2:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esi,hello
mov ebx,0xb8000
.loop:
lodsb
or al,al
jz halt
or eax,0x0100
mov word [ebx], ax
add ebx,2
jmp .loop
halt:
cli
hlt
hello: db "Hello world!",0
times 510 - ($-$$) db 0
dw 0xaa55
Code: Select all
.code16
start:
jmp boot
gdt_start:
.quad 0x0
gdt_code:
.word 0xFFFF
.word 0x00
.byte 0x00
.byte 0b10011010
.byte 0b11001111
.byte 0x00
gdt_data:
.word 0xFFFF
.word 0x00
.byte 0x00
.byte 0b10010010
.byte 0b11001111
.byte 0x00
gdt_end:
gdt_pointer:
.word gdt_end - gdt_start
.word 0x00
.word gdt_start
CODE_SEG = gdt_code - gdt_start
DATA_SEG = gdt_data - gdt_start
boot:
mov $0x2401, %ax
int $0x15
mov $0x3, %ax
int $0x10
cli
lgdt gdt_pointer
mov %cr0, %eax
or $0x1, %eax
mov %eax, %cr0
jmp $CODE_SEG, $boot2
.code32
boot2:
mov $DATA_SEG, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov $hello, %esi
mov $0xb8000, %ebx
.loop:
lodsb
or %al,%al
jz halt
or $0x0100, %eax
movw %ax, (%ebx)
add $2, %ebx
jmp .loop
halt:
cli
hlt
hello: .string "Here we are!!"
. = start + 510 # Fill the rest of the 510 bytes with '\0'.
.byte 0x55
.byte 0xAA
Code: Select all
#nasm
0000000 01b8 cd24 b815 0003 10cd 0ffa 1601 7c38
0000010 200f 66c0 c883 0f01 c022 3eea 087c 9000
0000020 0000 0000 0000 0000 ffff 0000 9a00 00cf
0000030 ffff 0000 9200 00cf 0018 7c20 0000 b866
0000040 0010 d88e c08e e08e e88e d08e 6abe 007c
0000050 bb00 8000 000b 08ac 74c0 0d0d 0100 0000
0000060 8966 8303 02c3 eeeb f4fa 6548 6c6c 206f
0000070 6f77 6c72 2164 0000 0000 0000 0000 0000
0000080 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200
#gnu as
0000000 1eeb 0000 0000 0000 0000 ffff 0000 9a00
0000010 00cf ffff 0000 9200 00cf 0018 0000 7c02
0000020 01b8 cd24 b815 0003 10cd 0ffa 1601 7c1a
0000030 200f 66c0 c883 0f01 c022 3fea 087c 6600
0000040 10b8 8e00 8ed8 8ec0 8ee0 8ee8 bed0 7c6b
0000050 0000 00bb 0b80 ac00 c008 0d74 000d 0001
0000060 6600 0389 c383 eb02 faee 48f4 7265 2065
0000070 6577 6120 6572 2121 0000 0000 0000 0000
0000080 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200
If I try to put the gdt in the same spot as nasm, the long jump gives me an error: Error: can't handle non absolute segment in `jmp'.
I'm trying really hard (for no particular reason) to avoid using nasm and only use gnu gcc tools, but I'm getting stuck on switching to protected mode.
Any thoughts/suggestions?