Hi
I am pretty new to assembly. I am trying to write some real mode bootsector code. I am using NASM.
I seem to be having trouble understanding how NASM or x86 real mode handle segments and offsets. Or something. In any case, something is going wrong somewhere and I don't understand why.
For the moment, I am mixing my code and data into one plain binary file. So what I want to do is set DS to the same as whatever CS is, so that I can use the location of data in the binary as the actual offset when referring to it in my code, which is what NASM does if you don't give it an origin, right? Although the bootsector code always gets loaded up at linear address 0x07C00, I like the idea of having my code be able to sit anywhere in memory.
Aaanyway, to my mind, the following code should work:
But it doesn't work.
When I boot using this code, my Vmware BIOS prints a single 'S' at the top left of the screen. I haven't tried it on other BIOS's yet. In any case, this is not the intended result. Shouldn't it print an 'H'?
I am aware of an easy workaround. I can just tell NASM to start at 0x07C00 (instead of default 0?) by adding a [ORG 0x07C00] to the start of the NASM code, and then setting DS to 0x0000, rather than setting it to CS. That's fine, and that's what I do for the moment, but Id still like to know why the above code doesn't work - what am I missing?
When I make a memory reference such as [message] in my NASM code, the segment is going to be DS, right?
Hmmm, I just had a bit of a think about it, and I think part of the problem is that I'm assuming that the IP starts at 0 when the bootsector code is loaded. But I can't get at the contents of IP, can I. NASM doesn't recognise it as a register. Hmmmmmmmmmm
Thanks in advance,
Phipple
I am pretty new to assembly. I am trying to write some real mode bootsector code. I am using NASM.
I seem to be having trouble understanding how NASM or x86 real mode handle segments and offsets. Or something. In any case, something is going wrong somewhere and I don't understand why.
For the moment, I am mixing my code and data into one plain binary file. So what I want to do is set DS to the same as whatever CS is, so that I can use the location of data in the binary as the actual offset when referring to it in my code, which is what NASM does if you don't give it an origin, right? Although the bootsector code always gets loaded up at linear address 0x07C00, I like the idea of having my code be able to sit anywhere in memory.
Aaanyway, to my mind, the following code should work:
Code:
[BITS 16] ; real mode is 16 bit
entry:
mov ax, cs ; copy CS to AX
mov ds, ax ; DS is now same as CS
mov al, [message] ; load AL with first byte of
; message
mov ah, 0x0E ; print byte in AL using BIOS
; interrupt 10h:0Eh
mov bx, 0x07 ; set character attributes
int 0x10 ; call BIOS interrupt
hang:
jmp hang
message:
db 'Hello World', 0x00
; plus code to fill up to 512 bytes with 0x55AA at the
; end - works fine, not important here
But it doesn't work.
When I boot using this code, my Vmware BIOS prints a single 'S' at the top left of the screen. I haven't tried it on other BIOS's yet. In any case, this is not the intended result. Shouldn't it print an 'H'?
I am aware of an easy workaround. I can just tell NASM to start at 0x07C00 (instead of default 0?) by adding a [ORG 0x07C00] to the start of the NASM code, and then setting DS to 0x0000, rather than setting it to CS. That's fine, and that's what I do for the moment, but Id still like to know why the above code doesn't work - what am I missing?
When I make a memory reference such as [message] in my NASM code, the segment is going to be DS, right?
Hmmm, I just had a bit of a think about it, and I think part of the problem is that I'm assuming that the IP starts at 0 when the bootsector code is loaded. But I can't get at the contents of IP, can I. NASM doesn't recognise it as a register. Hmmmmmmmmmm
Thanks in advance,
Phipple