Discuss Scratch
- Discussion Forums
- » Advanced Topics
- » Help with NASM assembly
- ninjaMAR
-
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
“printlib.asm”

“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
; 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
-
100+ posts
Help with NASM assembly
You should checkout https://github.com/mig-hub/mikeOS/blob/master/source/features/screen.asm
- kccuber
-
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
-
1000+ posts
Help with NASM assembly
https://github.com/mig-hub/mikeOS/blob/master/source/features/screen.asmI briefly looked at it. The print function is largely the same. You should checkout
How would I change it? Do you think this is a QEMU problem? for some reason, this looks like a text encoding issue to me. try setting the charset to UTF-8 or whatever.
- Chiroyce
-
1000+ posts
Help with NASM assembly
Since you're on macOS, open up TextEdit How would I change it?

and while saving do this

In VSCODE bottom right -

- ninjaMAR
-
1000+ posts
Help with NASM assembly
I think the problem is in the code itselfHow would I change it?snip
Last edited by ninjaMAR (Sept. 28, 2021 09:24:31)
- AmazingMech2418
-
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…
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
-
1000+ posts
Help with NASM assembly
I'm making an OS. Could you please help me a little more with the code? 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…
section .data msg: db "KewlOS",0
- ScratchCatHELLO
-
1000+ posts
Help with NASM assembly
Also, why are you using QEMU? That's mainly for OS dev…
because they’re doing OS dev
- ehx
-
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.
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
-
1000+ posts
Help with NASM assembly
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…I'm making an OS. Could you please help me a little more with the code? 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…section .data msg: db "KewlOS",0
- ehx
-
40 posts
Help with NASM assembly
ninjaMAR has put the code for their own print function in the OP, so they've already done that.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…I'm making an OS. Could you please help me a little more with the code? 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…section .data msg: db "KewlOS",0
- ninjaMAR
-
1000+ posts
Help with NASM assembly
snipThanks 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
-
1000+ posts
Help with NASM assembly
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: -snip-
ninjaMAR has put the code for their own print function in the OP, so they've already done that.
%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
-
40 posts
Help with NASM assembly
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- -snip-
ninjaMAR has put the code for their own print function in the OP, so they've already done that.
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.
- Discussion Forums
- » Advanced Topics
-
» Help with NASM assembly