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.
bootload.asm
(2.49 KiB) Downloaded 53 times
kernel.asm
(844 Bytes) Downloaded 78 times
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! :shock:

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