1

I am developing a simple bare-metal OS, and my function for printing strings works only on some strings (eg "Hello World") but not others (eg "Press F1 for help")

[ORG 0x7C00]
msg db "Press F1 for help",0

main:
    mov AH, 00h
    int 16h
    cmp AH, 0x3B
    je help 
    jmp main

help:
    mov si, msg
    call print
    jmp main

; Print library, invoke with "call print" example:
; msg db "Foobar",0
; mov SI, msg
; call print
%include "printlib.inc"
 
return:
    ret

times 510-($-$$) db 0;
db 0x55
db 0xAA

printlib.inc:

print:
    mov ax, 0x07c0
    mov ds, ax
    cld
    jmp .loop
.loop:lodsb
    or al, al ; zero=end or str
    jz .retn   ; get out
    mov ah, 0x0E
    mov bh, 0
    int 0x10
    jmp .loop
.retn:
    ret
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • "Press F1 for help" does not work, and the BIOS supplies the INT 10h function – Ramdomly Random May 31 '21 at 21:51
  • 1
    I'm not sure it qualifies as "bare metal" if you're using the BIOS. – Nate Eldredge May 31 '21 at 22:33
  • 1
    Basically a duplicate of [Segmentation fault when using DB (define byte) inside a function](https://stackoverflow.com/q/55642600) (putting DB where it will be executed as code). [Why is no code executed after a db directive?](https://stackoverflow.com/q/65832296) is the same problem in a bootloader. – Peter Cordes May 31 '21 at 23:31
  • Oh, you should also initialize the stack segment and stack pointer, since you use the stack in a number of places (`int, call, ret`). – Nate Eldredge May 31 '21 at 23:40

1 Answers1

2

The BIOS will always start execution at the first byte of the boot sector, and in your case that appears to be the string, so you're executing data. (The fact that you put in a label called main doesn't affect this; nothing looks at it.) It could be that your "Hello world" string just happens to correspond to instructions that don't totally break everything.

Try moving the string to be after all the code, or else insert a jmp main before it.

Also, you have an inconsistency between your ORG directive and your ds segment. Your boot sector gets loaded at linear address 0x7c00. You can think of this in segment:offset form as 0000:7c00 or 07c0:0000 (or other ways in between if you really want). So to access data in the boot sector, you either need to load ds with zero and use [ORG 0x7c00], or else load ds with 0x07c0 and use [ORG 0]. However, your code mixes the two.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82