Megidd
Megidd

Reputation: 7952

Memory referencing and use of labels in an assembly program loaded by BIOS to memory as the boot sector

I'm studying a book by Nick Blundell on OS development. It has an example on CHAPTER 3. BOOT SECTOR PROGRAMMING (IN 16-BIT REAL MODE), like below:

;
; A simple boot sector program that demonstrates addressing.
;
mov ah, 0x0e ; int 10/ ah = 0eh -> scrolling teletype BIOS routine

; First attempt
mov al, the_secret
int 0x10 ; Does this print an X?

; Second attempt
mov al, [the_secret]
int 0x10 ; Does this print an X?

; Third attempt
mov bx, the_secret
add bx, 0x7c00
mov al, [bx]
int 0x10 ; Does this print an X?

; Fourth attempt
mov al, [0x7c1e ]
int 0x10 ; Does this print an X?

jmp $ ; Jump forever.

the_secret :
        db "X" 

; Padding and magic BIOS number.
times 510 -( $ - $$ ) db 0

dw 0xaa55

In the book, it is mentioned that:

If we run the program we see that only the second two attempts succeed in printing an ’X’.

Well, that's not the result I'm getting from:

$ nasm BOOK_EXAMPLE.asm -f bin -o BOOK_EXAMPLE.bin
$ qemu-system-i386 BOOK_EXAMPLE.bin

My result is this:

enter image description here

It is implied that my QEMU BIOS is printing "X" at only third attempt. I didn't modify the book example, I wonder what I'm missing.


UPDATE

Object dump of my binary code shows that the hex ASCII code for "X" i.e. 0x58 is at memory address 0x7c00+0x001d=0x7c1d

$ od -t x1 -A x BOOK_EXAMPLE.bin 
000000 b4 0e b0 1d cd 10 a0 1d 00 cd 10 bb 1d 00 81 c3
000010 00 7c 8a 07 cd 10 a0 1e 7c cd 10 eb fe 58 00 00
000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa
000200

Therefore I replaced one code line with the following:

mov al, [0x7c1d ]

Now output is as expected:

enter image description here

Upvotes: 0

Views: 91

Answers (1)

Jester
Jester

Reputation: 58762

The last one is using is a fixed address. Due to how your code got assembled the X probably didn't end up at that address. You can ask for a listing file using -l option to nasm and see for yourself. Here, I get:

23                                  the_secret :
24 0000001D 58                              db "X" 

You can see it's address 0x1d not 0x1e. The book's assembler probably used a 3 byte jump for the preceding jmp $ thus the 1 byte difference. You can change that to jmp near $ and then the code will work as expected. You can also fix the address of course.

PS: it's a bad idea to leave ds uninitialized, you never know how the bios set it up. Common possibilities are 0x7c0 or 0 and this code only works in the latter case. In case ds=0x7c0 then only the second X appears.

Upvotes: 4

Related Questions