After making a small bootloader to teach myself assembly language, I noticed that the stosb
instruction does not seem to be work. I compressed the issue to a minimal example:
BITS 16
start:
mov ax, 07C0h
add ax, 288
mov ss, ax
mov sp, 4096
mov ax, 07C0h
mov ds, ax ;setting up stack
mov al, 'j'
mov di, buffer
stosb
mov si, buffer
jmp loops
loops:
mov ah, 0Eh
lodsb
cmp al, 0
je done
int 10h
jmp loops
done:
hlt
buffer times 64 db 0
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55
When this bootloader is run it should store the letter j
into a buffer, and then print that buffer to the display. The output should be:
j
When run it doesn't seem to print anything. What is the problem, and how can I fix it?
The solution was given by Michael Petch, Weather Vane, Jim Mischel, and GJ in the comments. To elaborate:
The STOSB
instruction implicitly stores data to [ES:DI]
, whereas the LODSB
instruction implicitly loads data from [DS:SI]
. You use STOSB
to write to buffer
and LODSB
to read from buffer
. However, you set the DS
segment register but not ES
. Therefore, you are not storing the 'j'
character to the same location that you are reading from.
The solution is just to set ES
along with DS
:
mov ax, 07C0h
mov ds, ax
mov es, ax
Note: You may also want to explicitly clear the direction flag before using string instructions (e.g. LODSB
, STOSB
) in your code. You can do this with the CLD
instruction. The BIOS would most likely leave the direction flag cleared before handing off to the bootsector (which is why it worked for you without the CLD
), but to be absolutely sure, you should clear the flag yourself.