Reputation: 11
I'm developing code in an x86 boot sector as part of learning OS development. I'm expecting my code to print this to the console:
Hello
I get this instead:
H
Why is it only printing one character and not the entire string? How can I fix this?
This is a snippet of my code:
mov ah, 0x0e
mov bx, string_p
add bx, 0x7c00
mov al, [bx]
int 0x10
jmp $
string_p:
db 'Hello',0
"then padding and magic number"
Upvotes: 1
Views: 2011
Reputation: 16825
The interrupt 10H
, with register AH
set to 0EH
(INT 10h/AH=0eh), will print the current character in register AL
. Ralf Brown's Interrupt List is considered the Bible of DOS and BIOS interrupts. It's a valuable source of information on what interrupts are available, how they work, and their side effects.
If you use INT 10h/AH=0eh you need to manually advance the string pointer for every character and print them out one at a time. Code like this should work:
org 0x7c00 ; starting address
bits 16 ; 16-Bit mode
main:
cli ; disable interrupts
cld ; clear direction flags
xor ax, ax ; set AX to 0
mov ds, ax ; set DS to 0
mov ah, 0x0e ; call 0EH bios call
mov si, string ; move starting address of `string` into SI
loop:
lodsb ; load byte at DS into AL, update (increment) SI
or al, al ; check if AL is 0 (ORing will do nothing, but set the right flags
jz hltloop ; if zero jump to end
int 0x10 ; do the print call
jmp loop ; jump back to loop start
hltloop:
hlt ; halt and catch fire
jmp hltloop ; jump back to halt, if an interrupt occurred anyway
string:
db 'Hello',0
times 510-($-$$) db 0
dw 0xAA55
This example uses the LODSB instruction to read each character of the string. The LODS instructions are documented as:
Loads a byte, word, or doubleword from the source operand into the AL, AX, or EAX register, respectively. The source operand is a memory location, the address of which is read from the DS:ESI or the DS:SI registers (depending on the address-size attribute of the instruction, 32 or 16, respectively). The DS segment may be over-ridden with a segment override prefix.
Upvotes: 4
Reputation: 11
This is late, but may help someone. I was having the same issue playing around developing an os on ubuntu. Here is what worked for me. I created a print function and called it after moving the address of my string into bx:
print_function:
pusha
mov ah, 0x0e
mov al, [bx]
int 0x10
cmp al, 0
jne increment
jmp the_end
increment:
add bx , 1
mov al, [bx]
int 0x10
cmp al, 0
jne increment
jmp the_end
the_end:
popa
ret
Upvotes: 0