Page 1 of 1
C kernel "Print" function
Posted: Thu Dec 23, 2004 12:00 am
by Ty
Hello everyone,
I have a question that has to do with coding a "print" function. I'v already gotton into pmode, and loaded my kernel at physical address 0x00001000. Here is my 'print' function so far:
Code: Select all
int print(void) {
char *vidmem = (char *)0xB8000;
char *string = "Loading...";
while(*string != 0) {
*vidmem++ = *string++;
*vidmem++ = 0x07;
}
return;
}
This code works perfectly. But, as soon as I change the declaration of print() from "int print(void)" to "int print(char *string)" and pass this function a string form my kernel, instead of printing the string, it seems to clear the screen. I figured that the problem had to do with my stack because that's where paramaters are passed. My stack segment (ss) starts at 0x0000. (which is from my ds descriptor base) and ends at esp=0x90000. I can't figure out what i'm doing wrong.
Thanks,
Ty
Re: C kernel
Posted: Fri Dec 24, 2004 12:00 am
by [AlAdDiN]
i dont think that the problem is due to ur stack, anyway, try to write some debugging functions and make sure that ur esp is positionned @ 0x90000
try this code
Code: Select all
int print(char *str) {
char *vidmem = (char *)0xB8000;
char *string = str;
while(*string != 0) {
*vidmem++ = *string++;
*vidmem++ = 0x07;
}
return;
}
Re: C kernel
Posted: Fri Dec 24, 2004 12:00 am
by Ty
You said:
Anyway, try to write some debugging functions and make sure that ur esp is positionned @ 0x90000
How would I make a debugging function? You mean with bochs? I'm using the win32 bochs, and havn't enabled debugging functuality. and don't know how. This is the kernel.c (so far) that calls print.c:
Code: Select all
extern int print(char *string);
int main(){
print("hello");
loop:
goto loop;
}
which calls print.c :
Code: Select all
int print(char *string) {
char *vidmem = (char *)0xB8000;
while(*string != 0) {
*vidmem++ = *string++;
*vidmem++ = 0x07;
}
return;
}
The kernel is compiled with->
gcc -c kernel.c
gcc -c print.c
ld -T link.ld kernel.o print.o
And here is my bootsector:
Code: Select all
[BITS 16]
[ORG 0X7C00]
jmp main
nop
main:
load_kernel:
.reset:
mov ah, 0x00
int 0x13
jc .reset
mov ah, 0x02 ; read sector function
mov al, 0x01
mov ch, 0x00
mov cl, 0x02 ; read second sector
mov dh, 0x00
mov dl, 0x00
mov bx, 0x00 ; segment
mov es, bx
mov bx, 0x1000
.read:
int 0x13
jc .read
.kill_motor:
mov dx, 0x3f2
xor al, al
out dx, al
cli
xor ax, ax
mov ds, ax
lgdt [gdtr]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp .next
.next:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000
jmp 0x08:0x1000
gdtr:
dw (8*3)-1
dd gdt
gdt:
dw 0x0000
dw 0x0000
dw 0x0000
dw 0x0000
dw 0xFFFF ; code descriptor
dw 0x0000
db 0x00
db 10011010b
db 11001111b
db 0x00
dw 0xFFFF ; data descriptor
dw 0x0000
db 0x00
db 10010010b
db 11001111b
db 0x00
times 510-($-$$) db 0
dw 0xAA55
Sorry if this is too much code. I thought that maybe if you guys saw my bootsector too, that you might see a problem off the top of your head.
Thanks, and Merry Christmas!
tyler
Re: C kernel
Posted: Sun Dec 26, 2004 12:00 am
by prajwal
Even I'm new to this field but I'll try to figure out this problem since I too
had a similar problem....
I think the problem is there with ORG statement....
The static string "hello" passed as parameter will be sotred in ur DS...
char *string points to that location where "hello" is stored...
But ORG 0x7c00 makes linker to resolve the address of "hello" by adding
0x7c00.... i.e....
if "hello" is there at address "0x1000" then char* string points to:
"0x1000 + 0x7c00"
To confirm this try a crude method....
char *x = "hello" ;
x = (x - 0x7c00) ;
print(x) ;
---- I think this should work..... Try this.....
The permanent Solution may be:
Don't set GDT, ds, es.... in boot loader... Load a file from this boot loader in 16 bit mode then in that file write code to enter pmode including
loading GDTR, ds, es etc... (all pmode stuff) and from there call ur C kernel main function
Re: C kernel
Posted: Mon Dec 27, 2004 12:00 am
by Ty
Thanks srinivasa_prajwal, I'll make a 'second stage' loader that will initiate pmode and set up the gdt. That'll most likely fix it. I tried this:
Code: Select all
char *x = "hello";
x = (x - 0x7c00);
But recieved a compilation error from gcc; it stated that there were confilicting types from the definition of 'x'. I then tried to asign the pointer with a pointer cast:
But it still won't allow it. I guess you can't re-asign values to so called "pointer constants" because of the way you asigned it. Oh well.
I'll try that second stage loader tonight to see how it works.
Thanks again!
Tyler
[/code]
Re: C kernel
Posted: Mon Dec 27, 2004 12:00 am
by Ty
Sorry, I forgot to ask something; I set my initial data segment's base address' to 0x0000. This is, of course, where the realmode interrupt vector table starts. Is this maybe the cause of the problem? Just a thought.
Thanks,
Tyler
EDIT: I just added a second stage loader that sets pmode and created a gdt, wich sets the ds and cs base to 0x90000, but it still doesn't work, does the same thing.