How do I set the instruction pointer on x86 Intel to point to my instruction?

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 jump instruction sets the IP register.

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.
Last edited on
The "jump if not equal" operand sets the instruction pointer to start at 0x0007cFF, not 0x0007c00, so how could it be an "infinite loop"?

I first jump to 0x0007c00 to bring memory in to EAX and AL, but after the comparison and branch test, it should jump to 7cFF, which is not infinite.
Last edited on
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.
Okay, I removed that, but it still doesn't work.

It assembles, and I assembled in to a flat .bin, but it won't execute the instructions(the processor).

I should see the byte representing the ASCII string on the screen.

PS: I'm using two different computer systems at once; one here, and the other is to test my machine code software.
Last edited on
You have move the value in to the AH register of 0x0E, set BH register to 0, move 0x07 to BL, then move the byte in to AL/SI and call the interrupt.

You can do this a few different ways, but the result is the same.

Also, it's not times 512($-$$).

The correction is --> times 510-($-$$) db 0 < --

That fills the rest of the 512 bytes, since you're only using four or five.

Last edited on
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.
Last edited on
It's times 510 - ($-$$) db 0.

Trust me on this one I've done this back in the old DOS days, so I would know.

PS: A label is the same as a memory offset.
Last edited on
It's my style, I write it how I please.

Hardcoded memory offsets are the same as labels, since labels are accessed via memory itself anyways, so there's no difference imo.

Also, I think TheMachineMaker is right, chrisname, because I did actually get the text on the screen using the correction he/she pointed out.

Thanks for your help guys!
Here's the screenshot:

http://postimage.org/image/3l0m7o6ud/
Yes, TheMachineMaker was right; my mistake.

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.
Last edited on
Topic archived. No new replies allowed.