Setting up Segment Registers, x86

70 Views Asked by At

I have a code:

[org 0x7c00]

CODE_SEG equ GDT_code - GDT_start
DATA_SEG equ GDT_data - GDT_start

cli
lgdt [GDT_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG:start_protected_mode

jmp $
                                    
                                     
GDT_start:
    GDT_null:
        dd 0x0
        dd 0x0
    GDT_code:
        dw 0xffff
        dw 0x0
        db 0x0
        db 0b10011010
        db 0b11001111
        db 0x0
    GDT_data:
        dw 0xffff
        dw 0x0
        db 0x0
        db 0b10010010
        db 0b11001111
        db 0x0
GDT_end:

GDT_descriptor:
    dw GDT_end - GDT_start - 1
    dd GDT_start

[bits 32]

start_protected_mode:
    mov ax, DATA_SEG
    mov ds, ax
    mov es, ax
    mov al, "A"
    mov ah, 0x0f
    mov [0xb8000], ax
    jmp $

times 510-($-$$) db 0
dw 0xaa55

It works fine on qemu, but when I try to boot it on the real pc, it just reboots. I found in the Internet, that my problem is Segment Registers. How can I set them up, so the program could start working on real PC?

I've tried to set DS and ES to 0x07C0, but then program stopped working on qemu too.

1

There are 1 best solutions below

4
Iman Abdollahzadeh On

First off, you have to set ds register to zero since you are set the origin address to org 0x7c00. This had been done by qemu and most probably with other virtual machines for you. But now during migrating to physical machine, you must take care of it yourself:

xor ax, ax
mov ds, ax
mov es, ax ; you may want this as well

Then, do not forget to set the stack with something like this or another area as you'd like:

mov ax, 0x9000
mov ss, ax
mov sp, 0xFC00 ; ss:sp (linear) -> 9FC00h (which is below BIOS area)