0

I am trying to make a basic OS with assembly. But this doesn't work. I don't know why. I'm a beginner by the way. The thing I want to do is to have print_string, use the function to print out boot_string. Code:

    BITS 16
start:
    mov ax, 07C0h
    mov ax, 288
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h
    mov ds, ax
    mov si, text_string
    call print_string
    jmp $         ; INFINITE LOOP



print_string:
    mov ax, boot_string
.repeat:
    lodsb
    cmp al, 0
    je .done
    int 10h
    jmp .repeat
.done:
    ret



    times 510-($-$$) db 0
    dw 0xAA55
boot_string    db 'Starting Operating System...', 0

But when I compile this it gives this error;

nasm -f bin -o os.bin os.asm
os.asm:13: error: symbol `text_string' undefined
os.asm:19: error: label `print_string' changed during code generation [- 
w+error=label-redef-late]
os.asm:21: error: label `print_string.repeat' changed during code generation [- 
w+error=label-redef-late]
os.asm:28: error: label `print_string.done' changed during code generation [- 
w+error=label-redef-late]
make: *** [Makefile:2: nasm] Error 1

I would be really happy if anyone can help me solve this. And if you know any sites about OS development, please give the URL so I can check them as well ^_^

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Arencos
  • 11
  • 3
  • There's no reference to `text_string` in your code. Are you sure these messages come from building the same version of the file that you've shown here? – Nate Eldredge May 25 '20 at 19:15
  • The code you've posted, with the nasm command you used, assembles without error for me. Is it possible you have two different versions of the file, or haven't saved the file in your editor? – Nate Eldredge May 25 '20 at 19:17
  • I changed it, sorry I was dumb, I copy pasted the wrong code – Arencos May 25 '20 at 19:18
  • Okay, well, now you refer to a string `text_string` which you never defined. So of course that isn't going to work. Did you mean to use `boot_string` instead? – Nate Eldredge May 25 '20 at 19:18
  • Ooooh, ok I removed mov si, text_string and it boots, but it doesn't print anything. – Arencos May 25 '20 at 19:19
  • Well yeah. Your `lodsb` is supposed to load bytes from the string pointed to by `si`, so if you don't have a pointer in `si` then you're going to get stuff from a random location in memory... – Nate Eldredge May 25 '20 at 19:21
  • I removed mov si, text_string, and instead of that added mov si, print_string. And it still doesn't work – Arencos May 25 '20 at 19:40
  • You have to remove that `mov ax, boot_string` from print string and replace it with `mov ah, 0eh` (AH=TTY Text Output) followed by a `mov bl, 0` to set the video page to 0 that you want to print to. Your `boot_string` is after the disk signature 0xaa55 - it needs to be before. The BIOS only reads 1 sector from a floppy/harddrive and your string is not within that first sector. With these fixes it could look something like: https://pastebin.com/q1uPX6Bk – Michael Petch May 25 '20 at 21:14
  • Hello! Update: I did everything you said, but it only prints random unicode characters. I cannot access pastebin, so can you post it somewhere else? – Arencos May 26 '20 at 12:36
  • Replace `mov ax, boot_string` with two instructions: `mov ah,0eh` , `mov bh,0` and then shift the definition of `boot_string` up, above `times 510-($-$$) db 0`. – vitsoft May 26 '20 at 15:21
  • I did it but it just shows random characters. Image: https://www.udrop.com/8Wd/qemu.png – Arencos May 26 '20 at 19:22
  • Did you try the version of my code here: https://pastebin.com/q1uPX6Bk that fixes your issues? – Michael Petch May 27 '20 at 12:10

1 Answers1

-1

The garbage indicates that VIDEO - TELETYPE OUTPUT is not fed from boot_string, i.e. DS:SI is not set properly when lodsb is performed.

CS:IP are the only two registers with defined contents at the start. Use CS to initialize the data segment register. Alternatively you could also use cs:lodsb instead of lodsb and leave DS undefined in the boot code.

       BITS 16
start:
    MOV AX,CS
    MOV DS,AX     ; Let the memory model be TINY.
    mov si, boot_string
    call print_string
    jmp $         ; INFINITE LOOP

print_string:
    MOV AH,0Eh    ; BIOS Teletype output
    XOR BX,BX     ; at videopage 0.
.repeat:
    lodsb
    cmp al, 0
    je .done
    int 10h
    jmp .repeat
.done:
    ret

boot_string    db 'Starting Operating System...', 0

    times 510-($-$$) db 0
    dw 0xAA55
vitsoft
  • 5,515
  • 1
  • 18
  • 31
  • I copy pasted this code, but now it prints nothing. – Arencos May 27 '20 at 09:59
  • YOu can't rely on the value of CS being what you expect it to be. Some BIOSes may set CS to 0x07c0 and some may set it to 0x0000. Copying CS to other registers is not a good idea. You don't have an `org 0x7c00` at the top so it defaults to 0x0000. An `org of 0x0000` requires a CS of 0x7c0 to be set. And Org of 0x7c00 requires CS to be 0. – Michael Petch May 27 '20 at 12:09
  • @MichaelPetch, you are right, `ORG 7C00h` is missing at the very start. Wiki says that CS:IP is *always* 0000:0x7C00, is it wrong? https://en.wikipedia.org/wiki/BIOS#Boot_environment – vitsoft May 27 '20 at 16:10
  • 1
    Wikipedia has a lot of misinformation on technical articles (I have corrected some already!). Wikipeadia is wrong when it says CS is always 0x0000 and IP is always 0x7c00. What is true is that the physical address to the start of the bootloader is physical address 0x07c00. However there is more than one way to reach that physical address. 0x07c0:0x0000 is physical address 0x07c00 and 0x0000:0x7c00 is also physical address 0x07c00. There are a variety of BIOSes that actually use 0x07c0:0x0000 and part of that came from wording in the CD-ROM Eltorito specification. – Michael Petch May 27 '20 at 16:23
  • I have revised Wikipedia. On a side note, in BOCHS the BIOS actually uses 0x07c0:0x0000 when booting CDROM media using floppy emulation. It uses 0x0000:0x7c00 when booting non-CDROM media. – Michael Petch May 27 '20 at 16:35