Discuss Scratch

ninjaMAR
Scratcher
1000+ posts

Help with NASM assembly

I'm learning NASM assembly and I decided to make an OS with it. I started to follow some tutorials but eventually I decided to go on my own. When I run my code, it should be printing “KewlOS” to the screen. Instead it prints a jumble of text. Could someone please help me? Included below are the files and the screenshot of the jumble of text.

“boot.asm” is the file being executed
;this is 16 bit mode BIOS
%include 'printlib.asm' ;use the utils file
mov dx,0 ; initalize main loop counter
main: ;main loop
	cmp dx,1 ;check if dx = 1
	jne main ; if !dx = 1 jump to main
	add dx,1 ; increase counter
	mov si,"KewlOS"
	call print_str
	
times 510-($-$$) db 0 ; fill rest of boot with '0'
dw 0xaa55 ; some sort of magic number
“printlib.asm”
; this file contains printing utilities
print_char:
	mov ah,	0x0E
	int 0x10
print_str:
	
	lodsd
	
	cmp al,0x00
	je .done
	
	call print_char
	
	jmp print_str
.done:
	ret

Last edited by ninjaMAR (Sept. 28, 2021 23:18:56)

u7p
Scratcher
100+ posts

Help with NASM assembly

You should checkout https://github.com/mig-hub/mikeOS/blob/master/source/features/screen.asm
kccuber
Scratcher
1000+ posts

Help with NASM assembly

for some reason, this looks like a text encoding issue to me. try setting the charset to UTF-8 or whatever.
ninjaMAR
Scratcher
1000+ posts

Help with NASM assembly

u7p wrote:

You should checkout https://github.com/mig-hub/mikeOS/blob/master/source/features/screen.asm
I briefly looked at it. The print function is largely the same.

kccuber wrote:

for some reason, this looks like a text encoding issue to me. try setting the charset to UTF-8 or whatever.
How would I change it? Do you think this is a QEMU problem?
Chiroyce
Scratcher
1000+ posts

Help with NASM assembly

ninjaMAR wrote:

How would I change it?
Since you're on macOS, open up TextEdit

and while saving do this


In VSCODE bottom right -
ninjaMAR
Scratcher
1000+ posts

Help with NASM assembly

Chiroyce wrote:

ninjaMAR wrote:

How would I change it?
snip
I think the problem is in the code itself

Last edited by ninjaMAR (Sept. 28, 2021 09:24:31)

AmazingMech2418
Scratcher
1000+ posts

Help with NASM assembly

Okay, your issue is that a string is actually an array of characters. Try setting in your data section an address to a string.

Basically, mov and lodsd doesn't work because the string isn't a primitive. Also, why are you using QEMU? That's mainly for OS dev…

Last edited by AmazingMech2418 (Sept. 28, 2021 20:27:13)

ninjaMAR
Scratcher
1000+ posts

Help with NASM assembly

AmazingMech2418 wrote:

Okay, your issue is that a string is actually an array of characters. Try setting in your data section an address to a string.

Basically, mov and lodsd doesn't work because the string isn't a primitive. Also, why are you using QEMU? That's mainly for OS dev…
I'm making an OS. Could you please help me a little more with the code?
section .data
msg:
    db "KewlOS",0
ScratchCatHELLO
Scratcher
1000+ posts

Help with NASM assembly

AmazingMech2418 wrote:

Also, why are you using QEMU? That's mainly for OS dev…

because they’re doing OS dev
ninjaMAR
Scratcher
1000+ posts

Help with NASM assembly

bump
ehx
New Scratcher
40 posts

Help with NASM assembly

You're doing several things wrong.
Your first issue is that you're including printlib.asm at the top of your code, this is causing the error you see on your screen. (Since you have a logic error under main that means it'll never execute the print code anyway)

%include just copies the contents of one file to another during assembling. Since the contents of printlib are what are at the top of the file, thats whats going to execute first, printing everything to the screen starting at whatever garbage addresses at left in ds:si from the BIOS.

Another issue you have is that you're trying to move a string in to the si register. This isn't valid at all, you should be using “db” to define a null terminated string alongside a label. The si (source index) register takes the address to some data, not the data itself. In real mode it's 16 bits, so you wouldn't be able to store a string in it even if you wanted to.

You have a major logic error in the first 4 lines after the include too, you move 0 in to dx, and then immediate compare dx to 1, and then when it isn't 1 go back to main. This creates an infinite loop and all the code afterwards just won't run. I'm not entirely sure why you're doing this but I would recommend not doing it at all, as reflected in the code below.

Furthermore, your print_str function is wrong too, you were using lodsd (load dword) rather than lodsb (load byte). This is an issue since lodsd will increase si by 4 each time it runs, rather than by 1, and since the length of each character in your string is 1 byte, you want to use lodsb.

Another issue is the fact you're calling print_char and not returning from print_char, this will end up filling the stack with data that will never be cleared, I'd recommend just not defining print_char separately and replacing the call to print_char with the code within print_char.

The modified code at the bottom of this reply will work. I've verified it with nasm and qemu myself. I would highly recommend you become more familiar with x86 assembler and the Intel x86 Architecture before continuing with your OS dev journey because it is extremely clear that you don't fully understand what you're doing, as indicated by the fact you've tried to move a string in to the si register.

I don't mean this in a negative way, its just that x86 assembler is very unforgiving and unless you understand what the instructions you're using are doing, you're going to cause yourself a lot of trouble in the future.

I would also recommend becoming familiar with the qemu monitor and how to use it to debug your own code.

;this is 16 bit mode BIOS
[ORG 0x7C00] ; BIOS loads the boot sector at 0x7c00, in order to address values properly we need to have this here. It makes the code generated act as though it started at 0x7c00.
main:
    mov si, message ; si register is 16 bit, you can't move a string in to it the way you're doing
    call print_str
    
    jmp $ ; Infinite loop, else the code will continue executing garbage 
    
message db "KewlOS", 0 ; print_str expects a null terminated string
    
%include 'printlib.asm' ;use the utils file
    
times 510-($-$$) db 0 ; fill rest of boot with '0'
dw 0xaa55 ; some sort of magic number

; this file contains printing utilities
print_str:
	
	lodsb ; You had lodsd here previously, but that loads a DWORD (32 bits / 4 bytes) and increments si by 4, which isnt correct, since every character is only 1 byte, not 4.
	
	cmp al,0x00
	je .done
	
	mov ah,	0x0E
	int 0x10
	
	jmp print_str
.done:
	ret
AmazingMech2418
Scratcher
1000+ posts

Help with NASM assembly

ninjaMAR wrote:

AmazingMech2418 wrote:

Okay, your issue is that a string is actually an array of characters. Try setting in your data section an address to a string.

Basically, mov and lodsd doesn't work because the string isn't a primitive. Also, why are you using QEMU? That's mainly for OS dev…
I'm making an OS. Could you please help me a little more with the code?
section .data
msg:
    db "KewlOS",0
Though, if you're making an OS, don't you need to make your own print function? Like I didn't think there was a native signal interrupt that would work… I might be wrong though…
ehx
New Scratcher
40 posts

Help with NASM assembly

AmazingMech2418 wrote:

ninjaMAR wrote:

AmazingMech2418 wrote:

Okay, your issue is that a string is actually an array of characters. Try setting in your data section an address to a string.

Basically, mov and lodsd doesn't work because the string isn't a primitive. Also, why are you using QEMU? That's mainly for OS dev…
I'm making an OS. Could you please help me a little more with the code?
section .data
msg:
    db "KewlOS",0
Though, if you're making an OS, don't you need to make your own print function? Like I didn't think there was a native signal interrupt that would work… I might be wrong though…
ninjaMAR has put the code for their own print function in the OP, so they've already done that.

ninjaMAR
Scratcher
1000+ posts

Help with NASM assembly

ehx wrote:

snip
Thanks for helping me. I decided to make the OS so I can learn NASM

Last edited by ninjaMAR (Sept. 30, 2021 00:24:53)

AmazingMech2418
Scratcher
1000+ posts

Help with NASM assembly

ehx wrote:

-snip-
ninjaMAR has put the code for their own print function in the OP, so they've already done that.

I don't think that's the same? It uses an interrupt, which I don't think you can do in native OS NASM. Based on LittleOSBook, you need something more like this:
%macro printchar 2
    mov eax, WRITESTART
    mov ebx, [position]
    add eax, ebx
    mov ebx, %1
    mov [eax], ebx
    mov ecx, eax
    add ecx, 1
    mov edx, %2
    mov [ecx], edx
    mov eax, [position]
    add eax, 2
    mov [position], eax
%endmacro
%macro printstr 3
    mov eax, %1
    mov [temp], eax
    mov eax, %2
    mov [templen], eax
    %%printstart:
    mov esi, [temp]
    mov esi, [esi]
    printchar esi, %3
    mov esi, [temp]
    add esi, 1
    mov [temp], esi
    mov esi, [templen]
    sub esi, 1
    mov [templen], esi
    mov al, [templen]
    cmp al, 0
    jne %%printstart
%endmacro

I did use macros instead of functions since this was a while ago, but I think you have to print right to the buffer with the data and can't use a basic interrupt since you don't have the library for that. IDK about 16-bit though because I've never used it. I've only ever really done 32-bit.


Edit: Full code: https://replit.com/@AmazingMech2418/HelloWorldOS#Loader.asm

Last edited by AmazingMech2418 (Sept. 30, 2021 03:04:37)

ehx
New Scratcher
40 posts

Help with NASM assembly

AmazingMech2418 wrote:

ehx wrote:

-snip-
ninjaMAR has put the code for their own print function in the OP, so they've already done that.

I don't think that's the same? It uses an interrupt, which I don't think you can do in native OS NASM. Based on LittleOSBook, you need something more -snip-

If you don't understand real mode, don't reply to a thread about real mode.

When in real mode, you can make use of many services provided to you by the BIOS to be able to write text to the screen, read from disk, etc.

In protected mode you have to do this all yourself as firmware cannot help you.

Powered by DjangoBB