OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 5:18 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Switching to Protected mode with gnu as
PostPosted: Tue Nov 08, 2022 4:01 am 
Offline

Joined: Sat Nov 05, 2022 2:55 am
Posts: 4
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.

Code:
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


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])

Code:
.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


However these produce very different assembly code:

Code:
#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


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?


Top
 Profile  
 
 Post subject: Re: Switching to Protected mode with gnu as
PostPosted: Tue Nov 08, 2022 11:07 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
They’re obviously going to produce different code as you have rearranged the sections. But you don’t say if the code works and, if not, what happens.


Top
 Profile  
 
 Post subject: Re: Switching to Protected mode with gnu as
PostPosted: Tue Nov 08, 2022 1:09 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
thebayliff wrote:
Code:
   .word gdt_end - gdt_start
   .word 0x00
    .word gdt_start

Why is ".word 0x00" in there?

Shouldn't that be ".long gdt_start" instead of ".word gdt_start"?


Top
 Profile  
 
 Post subject: Re: Switching to Protected mode with gnu as
PostPosted: Tue Nov 08, 2022 10:48 pm 
Offline

Joined: Sat Nov 05, 2022 2:55 am
Posts: 4
iansjack wrote:
They’re obviously going to produce different code as you have rearranged the sections. But you don’t say if the code works and, if not, what happens.


Apologies, the code from nasm works when compiled and it outputs on qemu a screen with the correct text "Hello World!" in blue text. The gnu as code triple faults and causes qemu to reboot.

Octocontrabass wrote:
thebayliff wrote:
Code:
   .word gdt_end - gdt_start
   .word 0x00
    .word gdt_start

Why is ".word 0x00" in there?

Shouldn't that be ".long gdt_start" instead of ".word gdt_start"?


This seems to be the problem. I knew it was supposed to be the nasm equivalent of dd, but I thought I was being smart by adding the high order byte being all 0s first (shouldn't try to outsmart anyone in assembly.)

I now have working protected mode execution using gnu as. Thanks all!


Top
 Profile  
 
 Post subject: Re: Switching to Protected mode with gnu as
PostPosted: Wed Nov 09, 2022 12:38 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
Just as a matter of interest, you could keep the program order the same as the example you are copying by defining the _SEG values at the head of the listing. Although you calculate them (which is the problem - gnu as doesn’t allow you to use them before you calculate them) you know that they are 0x08 and 0x10.


Top
 Profile  
 
 Post subject: Re: Switching to Protected mode with gnu as
PostPosted: Wed Nov 09, 2022 9:05 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
thebayliff wrote:
I thought I was being smart by adding the high order byte being all 0s first

It would have worked, but x86 is little-endian. You have to put the low-order word first.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: 8infy, Bing [Bot], Majestic-12 [Bot] and 67 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group