Page 1 of 1
[SOLVED] ASM Kernel
Posted: Fri Oct 29, 2010 8:18 pm
by HiGuys
Hello everyone. I've decided to re-write my kernel(I wasn't too far anyway) from C/ASM to just ASM. This is for the purpose of using less resources and increasing speed. I've had a problem with printk for a while with it. I can print one character, but not a string. The code is as follows:
Code: Select all
[GLOBAL print_one]
[GLOBAL printk]
screen_x equ 0
screen_y equ 0
string db "Hello, World!", 0
new_line:
mov byte [screen_x], 0
add byte [screen_y], 1
ret
print_one:
; Temporarily use bx as a storage spot for the attrib/char
mov bh, 0x0F
mov bl, al
; Multiply the screen_y by 160 and put it in cx (attrib/char each column, times 80 columns per row)
mov ax, [screen_y]
mov cx, 160
mul cx
mov cx, ax
; Multiply the screen_x by 2 and put it in dx (attrib/char each x value)
mov ax, [screen_x]
mov dx, 2
mul dx
mov dx, ax
; Put the attrib/char back into ax
mov ax, bx
; Put the x and y values into bx
mov bl, dl
mov bh, cl
; Put the video memory location into edi, then add on the x and y values
mov edi, 0xb8000
mov [es:edi], bx
; Put the attrib/char into video memory (At this time - AX=ATTRIB+CHAR, BX=X+Y, ES:EDI=VIDEO MEMORY+BX, DX=X, CX=Y)
stosw
; Increment x
add byte [screen_x], 1
; If the x value is on the last value, goto a new line.
cmp byte [screen_x], 80
je new_line
ret
printk:
; Put the sring in al, increment si, which contains a pointer to a string
lodsb
inc si
; If al = 0x00, end of string
cmp al, 0
je done
; Else, print the character
call print_one
jmp printk
done:
mov al, 'D'
call print_one
call new_line
I believe I've isolated the problem to the first line of printk, it's loading a 0 instead of the first byte of the string, which makes it stop, and I can't figure out why.
Re: ASM Kernel
Posted: Fri Oct 29, 2010 9:51 pm
by Chandra
This might help you...
Code: Select all
column dw 0
row dw 0
string db "Hello, World!", 0
string2 db "Next test in progress...",0
done db "All test sucessfull!",0
mov si,string
call printk
mov si,string2
call printk
mov si,done
call printk
cli
hlt
printk:
mov ax,0xb800
mov es,ax
call printchar
ret
printchar:
mov di,[row]
mov al,[si]
cmp al,0
jz finished
mov [es:di],al
mov bx,[row]
inc bx
inc bx
mov [row],bx
inc si
jmp printchar
finished:
call nextline
ret
nextline:
xor ax,ax
mov ax,[column]
inc ax
mov [column],ax
mov bx,[row]
xor bx,bx
mov cx,160
mul cx
mov [row],ax
ret
I don't know if this is the best way to do but it works. Also remember that since you want to call this from external file, declare row, column, printk and printchar as global type.
[Note: Row is updated every time you print a character and column is updated everytime you change the line. So you need not worry about what value they carry ]
Re: ASM Kernel
Posted: Fri Oct 29, 2010 11:40 pm
by HiGuys
I don't know how you got that to work, you can't move a string into si because the string is bigger. You would have to move it into esi, which doesn't work for me.
Re: ASM Kernel
Posted: Sat Oct 30, 2010 1:26 am
by Chandra
I don't know why it didn't work with you. I tested the code myself and works fine with me.
I'm using this code in my bootloader and it works fine with me.Are you sure you've setup the proper segment registers? I'll attach the sample bootloader and the kernel file(very simple one) here.
Do assemble and let me know if this works or not.
Also note that I've not introduced filesystem yet so you must write the kernel to 2nd sector exactly after the bootloader(1st Sector) for this to work.
Best Regards,
Chandra
Re: ASM Kernel
Posted: Sat Oct 30, 2010 5:33 am
by Combuster
<Insert something about spoonfeeding being the worst kind of answer>
Re: ASM Kernel
Posted: Sat Oct 30, 2010 6:35 am
by Chandra
Oh, Really?
If you feel that's like spoonfeeding , a very big SORRY!
Re: ASM Kernel
Posted: Sat Oct 30, 2010 6:44 am
by Solar
The only solution is understanding. Providing a piece of source code is usually not the best way to foster such understanding. HiGuys wanted to understand why his kprintf loads a zero instead of the first character of the string. A good solution would give him not only a functional kprintf function, but also the knowledge not to make that particular mistake again.
Consider this: "I want to write my own OS but it doesn't work." - "Here, take Linux, that works."
Re: ASM Kernel
Posted: Sat Oct 30, 2010 9:17 am
by HiGuys
Solar wrote:The only solution is understanding. Providing a piece of source code is usually not the best way to foster such understanding. HiGuys wanted to understand why his kprintf loads a zero instead of the first character of the string. A good solution would give him not only a functional kprintf function, but also the knowledge not to make that particular mistake again.
Consider this: "I want to write my own OS but it doesn't work." - "Here, take Linux, that works."
Yes, I do want to understand the code a little better, I got what most of the code is doing, just not the first lines of printk. On another note, this is an error coming from the linker, not the assembler. Does that have anything to do with it? All your code is in one file so you probably assemble that directly into the kernel. My code is split across three different files, and nasm won't take more than one, so I use ld. Is this a mistake?
Re: ASM Kernel
Posted: Sat Oct 30, 2010 9:21 am
by NickJohnson
Are you using ELF (or PE) as an object format, or just flat binary? Flat binary objects cannot be linked. If you want to make your kernel a flat binary but you also want multiple files, you need to use ELF first (-felf for nasm), link the produced objects with ld, then convert the ELF executable to a flat binary.
Re: ASM Kernel
Posted: Sat Oct 30, 2010 10:18 am
by HiGuys
NickJohnson wrote:Are you using ELF (or PE) as an object format, or just flat binary? Flat binary objects cannot be linked. If you want to make your kernel a flat binary but you also want multiple files, you need to use ELF first (-felf for nasm), link the produced objects with ld, then convert the ELF executable to a flat binary.
I was using aout format, now I switched to ELF and it say's "File format not recognized". Could this be that I'm running ld from DJGPP?
Re: ASM Kernel
Posted: Sat Oct 30, 2010 11:08 am
by azblue
If al is being loaded with a zero than ds:si is pointing to a zero. Make sure your string pointer is set up correctly.
I see quite a few other problems too. mov [es:edi], bx does not add the contents of bx to edi, it loads the contents of bx into the 1st 2 bytes of the video memory.
Not only that, the contents of bx don't seem right anyway. You need it to be y*160+x*2. After computing y*160, you then load the lower 8 bits of it into the bh. That would only work if the screen width was 128 characters. It's not, so you end up with a number in bx that is essentially meaningless.
In printk, stosb increments si once, and then inc si increments it again. Get rid of the 2nd increment.
Re: ASM Kernel
Posted: Sat Oct 30, 2010 11:12 am
by azblue
Higuys, are you in protected mode or real mode? Are all your segments 4GB? If ds if a 4GB segment and you're only using si, all you're doing is setting the lower 16 bits of esi while leaving the upper 16 to whatever they were before you called printk; that could be why your string pointer is wrong. Use esi, in addition to making the other corrections I mentioned.
Re: ASM Kernel
Posted: Sat Oct 30, 2010 11:30 am
by Owen
HiGuys wrote:NickJohnson wrote:Are you using ELF (or PE) as an object format, or just flat binary? Flat binary objects cannot be linked. If you want to make your kernel a flat binary but you also want multiple files, you need to use ELF first (-felf for nasm), link the produced objects with ld, then convert the ELF executable to a flat binary.
I was using aout format, now I switched to ELF and it say's "File format not recognized". Could this be that I'm running ld from DJGPP?
DJGPP does not use or support Elf; it uses DJGPP-COFF