I'm trying to make a very basic function in assembly - printing to screen using video memory instead of BIOS interrupts. I already have a basic bootloader that just loads this sector into memory at 0x7E00. It is correctly loaded into memory. However, it prints very unexpected results for all the strings I have tested so far, with no pattern in between.
Using GDB, I was able to see what was loaded into the AL register each time lodsb
was called. For example, using the string "Mesting!", the string that appeared on screen was "#fsting!". For the first two characters, the hex representation of "#" and "f" were loaded in the first two times, as expected with that output. With "Hello World!", it only printed the first two "He" characters before terminating. On the third iteration, lodsb
loaded 0x0 into the AL register, instead of "l", causing it to terminate (as the string is null terminated). With the string "testing!", nothing was printed onto the screen and the assembly code displayed in GDB was a je
operation that caused it to jump past all the subsequent code. Yet with the string "Testing!", with a capital "T", the capital "T" was replaced with a strange character (hex representation "0xDE") and the consecutive characters "esting!" printed perfectly. Both the strings "Ttesting!" and "tTesting!" caused the same effect as the string "testing!".
I am understandably confused as to why there are strange characters being loaded into the AL register and some strings just don't work at all and jump past all the assembly (according to GDB). I am running this all in QEMU i386. Why is this happening? My code is below.
org 0x7e00
bits 16
msg db 'Mesting!',0h
jmp Main
Main:
mov dx,0xb800
mov es,dx
mov si,msg
xor cx,cx
xor dx,dx
jmp Print
Print:
lodsb
cmp al,0h
je .term
mov di,cx
mov byte [es:di],al
inc cx
mov di,cx
mov byte [es:di],0x0a
inc cx
jmp Print
.term:
ret