I think there are some copy and paste errors in your example code. You wrote:
xchg bx, bx
mov ax, 7c0h
mov ds, ax
But I think you meant:
xchg bx, bx
mov ax, 7c0h
mov es, ax ; Int 10h/ah=13h takes string address in ES:BP
Your code was correct in the very first snippet. Your example has two sector_2
labels so would probably cause NASM some grief. I believe you should just remove the first appearance of the label in your code.
I assume you are assembling your code with something like:
nasm -f bin boot.asm -o boot.img
The file names will be different and you can omit the -f bin
since it is default.
Since your code doesn't have an explicit ORG directive in it, NASM assumes org 0h
by default. All absolute memory references are relative to an offset of 0. In your case that is what you want for the first sector (512 bytes) of your assembler file. You have coded your bootloader to use a segment of 0x7c0
, the segment you choose and an origin point of 0 should point to a physical address of 7c00h. In segment:offset addressing you'd have (7c0h<<4)+0 (where 0 is the origin/org) which yields the proper result of 7c00h.
So all is well and good, you properly read the sectors into memory at 900h:0h. You then do a FAR CALL to it from the first stage of your bootloader via call 900h:0000
. This too is correct.
If all this is correct where is the problem? The issue is that NASM has no idea you loaded the code after the first 512 bytes to another location in memory and that the segment:offset used would be relative to 0 again (900h:0000h). It will continue to generate absolute addresses relative to the beginning of your bootloader.
If you were to use NDISASM to display the generated code starting from byte 512 of your disk image you'd discover the problem:
00000000 B80009 mov ax,0x900
00000003 8EC0 mov es,ax
00000005 BD1A02 mov bp,0x21a
00000008 B413 mov ah,0x13
This was generated with the command:
ndisasm -e 512 -b16 boot.img
boot.img
is the name of the image file you generated. The -e 512
says to skip disassembling the first 512 bytes of the file. I'm just interested in the first few lines of the output, in particular:
mov bp,0x21a
0x21a
is the offset of hello
. But notice that 0x21a
is 538 decimal and that would be the offset relative to the beginning of the entire bootloader not relative to an offset of 0 (900h:0000h). To fix this, you need to instruct NASM that the code generated in the second stage (second sector) needs to be relative to an origin of 0 and not relative to the beginning of the bootloader. This can easily be done by placing the second stage (second sector) in a new section where the origin point (vstart) is reset to 0. That can be done by placing a section directive like this at the beginning of the second stage:
section stage2, vstart=0h
So in your code it would look like:
dw 0aa55h ; Define MAGIC number at byte 512
;;;;;;;;;;;;;;;;;;;;;;;;
section stage2, vstart=0h ; Section name can be anything of your choosing
sector_2:
mov ax, 900h
mov es, ax
mov bp, hello
Now if you look at the NDISASM output it would look like:
00000000 B80009 mov ax,0x900
00000003 8EC0 mov es,ax
00000005 BD1A00 mov bp,0x1a ; Notice hello offset is 0x1a not 0x21a
@Jester was on the right track with org 0h
being placed before the second stage code (second sector), but there can only be one ORG directive in each assembly file. No matter where you place it in the file, NASM will act as if it actually found it at the top of the file. This behaviour is not well documented! Jester's solution wouldn't have changed anything. NASM's `SECTION directive can be used anywhere in the assembly file to reset the origin point (in this case to 0).
More information on the ORG and SECTION directives can be found in the NASM documentation. The SECTION directive and the VSTART argument are documented in section 7.1.3 Multisection Support for the bin Format
sector_2
is at offset 512, when in fact it's at offset 0. You might try to useorg 0
there. – Walterorg 900h
insector_2
and it doesn't do anything. – Ninonorg 900h
is wrong, was I not clear aboutorg 0
? You need to set the offset, not the segment. – Walter