I am writing a super-simple bootloader, yet after reading tuts, I can't seem to get the idea here.
I tell FASM I want 16 bit opcodes for P6 microarchitecture, I specify the origin at 0x0007c00, I set a jump to that origin, and start setting things up.
However, it doesn't work.
Is this code the problem, perhaps?
1 2 3 4 5 6 7 8 9 10 11 12 13
BITS 16
ORG 0x0007c00
JMP 0x0007c00
MOV EAX, 0x00F
MOV AL, 0x00F
CMP EAX, AL
JNE 0X007cFF
MOV AL, 0x03
MOV SI, STRING
INT 0x10h
STRING db 'HELLO', 0
times 512($-$$)
dw 0xAAFF
The reason your code doesn't work is because your first jump instruction is an infinite loop. Think about it. BITS and ORG are not instructions, they're assembler directives, so they get removed from the executable. The first thing the CPU sees when it executes your code is your jump to 0x7c00. Now, where does the BIOS load your program? At 0000:7c00. In short, you're jumping back to the jump instruction.
You misunderstand. Your jump to 0x7c00 is at 0x7c00, so it's jumping to itself; hence, an infinite loop.
The BIOS loads the bootloader to 0x7c00 in memory and then jumps to it. The CPU then blindly executes whatever instruction is there. In your case, the instruction at 0x7c00 tells the CPU to jump to 0x7c00, so it does. Then it executes the instruction there, which tells it to jump to 0x7c00 again, so it does, and so on, ad infinitum. That's why it's not working. Take out jmp 0x7c00 and it should work.
Why are you using hardcoded memory offsets instead of labels, and why did you write "0x10h" (0x10 = 10h)? Also your times directive is wrong, it should be times 512 - ($ - $$) db 0. The BIOS probably isn't even loading the executable because there won't be a boot signature at the 511th byte.
I know that labels and memory offsets are the same, but labels are much easier to use and understand: if you change your code, you don't have to recalculate the offset yourself, labels split your code into neat blocks, it's much easier to figure out where the jump is going when it's to a label and it's generally easier to reason about the flow of control. Using hardcoded offsets when labels are more appropriate is stupid; you're making more work for not only yourself, but everyone who looks at your code. When you ask for help, do you expect people to be sitting there trying to figure out where in your program is FF bytes after the origin? Am I meant to look up an x86 instruction reference to figure out how many bytes each instruction and its arguments takes up in the executable file when it's assembled? Just use labels.
WalkerRoger12 wrote:
labels are accessed via memory itself anyways
No, the labels are removed where you declare them and converted into offsets where you use them. They don't make it into the final executable.