Here's my ASM code:
bits 16
org 0x7c00
boot:
mov bx, string
call print_string
hlt
string:
db 'Booting OS', 0
printloop:
; Move the character into al so the BIOS interrupt prints it
mov al, [bx]
int 0x10
; Increment bx by 1 so it goes to the next character of the string
add bx, 1
; Check if the value is 0, if so, exit out of the loop, if it's not 0, continue looping
mov cx, [bx]
cmp cx, 0x0000
jne printloop
jmp print_fin
print_string:
pusha
mov ah, 0x0e
jmp printloop
print_fin:
popa
ret
; Mark the device as bootable
times 510-($-$$) db 0 ; Add any additional zeroes to make 510 bytes in total
dw 0xAA55 ; Write the final 2 bytes as the magic number 0x55aa
Here's the output of the code:
Booting OS ŠÍƒÃ‹ƒù uòë`ëíaÃß
I'm fairly sure that's not what I entered.
I have no idea why it's going past the terminator..
Edit: I just tried setting the byte at the end of the string to 0x0000
, incase that's somehow different from 0
, it still went right past the terminator.
CodePudding user response:
This is one of those errors that would have gone by unnoticed if you had written the string right above the TIMES
directive (and thus below the rest of the code). The first padding zero would have made it OK.
...
string:
db 'Booting OS', 0
times 510-($-$$) db 0
dw 0xAA55
Edit: I just tried setting the byte at the end of the string to
0x0000
, incase that's somehow different from 0, it still went right past the terminator.
Your edit could have solved the problem were there no misconception about what 0x0000
means. The way you write your numerical constant does not impose any size information on the DB
directive.
db 'Booting OS', 0
db 'Booting OS', 0x00
db 'Booting OS', 0x0000
db 'Booting OS', 0x00000000
All the above encode the same, appending a single zero byte to the text.
Your effort to solve it using 0x0000 would have worked via the DW
directive, appending a single zero word to the text:
db 'Booting OS'
dw 0x0000
But even here, you could have written the terminator in many ways:
dw 0
dw 0x00
dw 0x0000
dw 0x00000000
Unrelated to the bounds issue, but the print_string code is way too complicated. Better use code like this:
mov si, string
call print_string ; -> SI (AX)
...
; IN (si) OUT (si) MOD (ax)
print_string:
push bx
mov bx, 0x00007 ; BH is DisplayPage, BL is GraphicsColor
jmp .begin
.loop:
mov ah, 0x0E ; BIOS.Teletype
int 0x10
.begin:
mov al, [si] ; \ Alternatively, you can use LODSB here
inc si ; /
cmp al, 0
jne .loop
pop bx
ret
CodePudding user response:
I've fixed it, the problem was that I was using a 16 bit register to compare an 8 bit one (cx
instead of cl
), and the cmp
was comparing the wrong values. (If I've gotten this wrong, please tell me what I got wrong. I've only just started learning ASM)