I have two variants of code for bootloader (it should move 1kb stack after 512b of a bootloader code). Start physical address is always 0x7c00 (label "start"). BIOS copies a bootloader code in RAM. When I use "MOV SP, start+1024+512":
- SP will be 0x7c00 + 1024 + 512, because physical address should be SS:SP = 0<<4 + 0x7c00 + 1024 + 512. So "start" = 0x7c00
- SP will be 0 + 1024 + 512, because physical address should be SS:SP = 0x07c0<<4 + 1024 + 512. So "start" = 0x0000
But if I write "jmp start" proccessor will always go to the address 0x7c00. It will calculate
- 0 + 0x07c0
- 0x07c0<<4 + 0
Why does 'start' return different values in MOV and LMP? Or it will be the same, but in MOV proccessor doesn't add segment, and in JMP adds? Also is it true that in this case "start" will be calculated based on DS:SI and not CS:IP? Another example. If I add code in the end
mov SI, main
lodsb ;write data from main to AL
Proccessor will always go to the full physical address segment+offset and get value 'S' in register AL. SI will be equal to offset only? And processor will add segment during execution of lodsb?
Extra questions:
How does processor execute "jmp main"? This instruction is above "mov ds, ax". Therefore code in the 2 variant has an error, but it works.
What is the value of CS register by default when BIOS loads bootloader? Obviously CS:IP should be 0x7c00.
1 variant
[bits 16]
[org 0x7c00]
start: ;offset= 0x7c00
jmp main
db "Some data" ;actually fake BIOS Parameter Block(BPB)
main:
mov ax, 0
mov ds, ax ; data segment =0.
mov ss, ax ; stack segment = 0
mov sp, start+1024+512 ;stack pointer = 0x7c00+1024+512
2 variant
[bits 16]
[org 0x0000]
start: ;offset= 0x0000
jmp main
db "Some data" ;actually fake BIOS Parameter Block(BPB)
main:
mov ax, 0x07c0
mov ds, ax ; data segment =0x07c0.
mov ss, ax ; stack segment =0x07c0.
mov sp, start+1024+512 ;stack pointer = 0+1024+512