Problem
I have assembly code that switches to 32bit mode and prints a character successfully when I have it inside the boot sector - But when I use a disk read to load the code to the next sector the GDT table is misplaced even with the org directive, print fails, and the program gets into a boot loop. The disk read is successful, I tested it, and the code is exactly same in both cases except that I'm using org 0x7C00 in boot sector and 0x7E00 in 2nd sector.
I tried removing org and replacing dd gdt_start with dd gdt_start + 0x7E00, as well as hard-coding the exact address.
Project details
- Writing x86_64 assembly
- Running with QEMU
Working code sets GDT table to the right address containing 7C03, 3 bytes after the start. Not working code sets GDT to 000f61e0 00000037 (Not even close to right)
Stage 2 code:
BITS 16
org 0x7E00
cli
jmp code
gdt_start:
dq 0x0000000000000000 ; Null descriptor
dq 0x00CF9A000000FFFF ; Code segment
dq 0x00CF92000000FFFF ; Data segment
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; Size
dd gdt_start
code:
lgdt [gdt_descriptor]
mov eax, cr0
or eax, 1 ; Change PE (Protection Enable) bit if 0
mov cr0, eax
jmp 0x08:protected_mode
[BITS 32]
; Registers are 16-bit and map to 32-bit addresses through GDT table
protected_mode:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, 0xB8000
mov byte [eax], 'D'
mov byte [eax+1], 0x01
jmp $
And in case you want to see the disk read code from first stage:
BITS 16
org 0x7C00
jmp code
boot_drive: db 0
code:
mov byte [boot_drive], dl ; dl is loaded at boot and has the source drive
xor ax, ax
mov ah, 0x02 ; Disk read
mov al, 3 ; Sector read count
mov ch, 0 ; Cylinder
mov cl, 2 ; Sector
mov dh, 0 ; Head
mov dl, [boot_drive] ; Drive
mov es, ax ; Segment
mov bx, 0x7E00 ; Offset
int 0x13 ; Disk service
jc error ; Jmp if CF = 1
jmp 0x0000:0x7e00
error:
mov ah, 0x0E
mov al, 'E'
mov bh, 00
mov bl, 0x07
int 0x10
times 510 - ($ - $$) db 0
dw 0xAA55
mov es, axline uses the 0203h you wrote toax. Recall thatalandahare halves ofaxso settingmov ah, 02hoverwrites a part ofaxfor instance.times ... db 0data. You should use an infinite loop here as well, or do something like calling int 16h function 00h (wait for keypress) then int 19h (reboot).dsandss:spin the first stage, andespin the second stage.org 7C00h, you need DS=0. For the stack you could choose SS=0 with SP=7C00h, putting it below the bootloader.