1

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
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
fluc
  • 11
  • 1
  • 1
    Assuming your first stage jump to `0x7e00`, you're executing the string data as bytes of machine code. Since you strangely put it before the `jmp Main`, making that instruction into a no-op (just a jump to the address directly following the jmp where execution would go anyway, if execution ever reached the jmp). If you set a watchpoint on the early part of the string, you'll be able to see when it gets stepped on. – Peter Cordes May 08 '22 at 07:25
  • 1
    Make sure `ds` is set up correctly. – fuz May 08 '22 at 11:46

0 Answers0