Page 1 of 3
kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 7:22 am
by guest
hi can anybody say me what is the probleme whith this code??
when I load this with my own bootlaoder the kernel only prints ' ' on the screen (test[0]...test[3] == 0 !!!). when I load this with the bootf02 by John S. Fine all works fine. what can be the problem???
Code: Select all
int main()
{
char* videomem = (char*)0xB8000;
char test[] = "LALA";
// doesn't work: prints only ' ' on the screen
videomem[0] = test[0];
videomem[1] = 7 ;
videomem[2] = test[1];
videomem[3] = 7 ;
videomem[4] = test[2];
videomem[5] = 7 ;
videomem[6] = test[3];
videomem[7] = 7 ;
/* works fine with both bootf02 and my own
videomem[0] = 'L';
videomem[1] = 7 ;
videomem[2] = 'A';
videomem[3] = 7 ;*/
return 0;
}
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 7:43 am
by frank
Code: Select all
char* videomem = (char*)0xB8000;
char test[] = "LALA";
I think these need to be unsigned char, not (signed) char.
The difference is that with signed 0x07 is at 128+7 not at 0x07
Code: Select all
// doesn't work: prints only ' ' on the screen
videomem[0] = test[0];
videomem[1] = 7 ;
videomem[2] = test[1];
videomem[3] = 7 ;
videomem[4] = test[2];
videomem[5] = 7 ;
videomem[6] = test[3];
videomem[7] = 7 ;
Why not put this in a loop, or if you're going to test it anyway only print 1 character.
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 8:03 am
by guest
I changed it but it doesn't work. the problem is that every item of the array test is 0. thats only an example later i will put all in a loop (and use a function etc.)
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 8:30 am
by frank
Something must be wrong / forgotten in your bootup.
This code (basically the same as yours) works:
Code: Select all
unsigned char* vm = (unsigned char*)0xB8000;
unsigned char ar[50] = "TEST";
vm[0] = ar[0];
vm[1] = 0x07;
Post your bootloader code
I think it's your stack or the segments you haven't re-set after switching to protected mode.
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 8:39 am
by guest
thats the function which enters pmode:
Code: Select all
enter_pmode:
cli
lgdt [gdt_desc]
mov eax, cr0 ; enable pmode
or eax, 1
mov cr0, eax
mov eax, DATA_SEL
mov ds, eax
mov es, eax
mov ss, eax
mov esp, 0xFFFF
jmp CODE_SEL:0x1000
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 8:47 am
by frank
enter_pmode:
cli
lgdt [gdt_desc]
mov eax, cr0 ; enable pmode
or eax, 1
mov cr0, eax
mov eax, DATA_SEL
mov ds, eax
mov es, eax
mov ss, eax
mov ds,eax
mov gs,eax
mov fs,eax
mov ax, point to your stack
mov ss,ax
mov esp, 0xFFFF
jmp CODE_SEL:0x1000
You forgot to set a few segments including the stack segment.
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 8:59 am
by guest
I set the stack to DATA_SEL address, or??
mov eax, DATA_SEL
mov ds, eax
mov es, eax
mov ss, eax
mov esp, 0xFFFF
jmp CODE_SEL:0x1000
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 9:26 am
by frank
You should point it to your stack segment.
I don't know where your stack segment starts nor how big it is.
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 9:37 am
by guest
OK I added this to my code:
Code: Select all
mov ds,eax
mov gs,eax
mov fs,eax
mov ax, STACK_SEL
mov ss,ax
and this to my GDT:
Code: Select all
; stack descriptor
STACK_SEL equ $-gdt
dw 0xFFFF ; limit 15:0
dw 0x00 ; base 15:0
db 0x00 ; base 23:16
db 0x92 ; access byte: present, ring0, code/data segment, non-executable, non-conforming, writeable, not-accessed
db 0xC0 ; flags: Granularity, 32-bit
db 0x00 ; base 31:24
but it doesn't work.
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 9:55 am
by frank
Post the whole source code or compare your code to john's. (since that one works, you must have forgotten something)
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 10:02 am
by guest
my boot.asm:
Code: Select all
[BITS 16]
[ORG 0x7C00]
ALIGN 4
jmp start ; jump to the code // if any other things a decleared after this
%include 'gdt.inc'
msg_ok db "OK",10,13,0
msg_failed db "Failed!!!",10,13,"Halt CPU",0
msg_enable_a20 db "Enable the A20 Gate...",0
msg_load_kernel db "Load the Kernel...",0
msg_check_cpu db "Check if CPU is >= 368...",0
msg_need_368 db "Failed",10,13,"Sorry your CPU must be a 368 or better",0
bootdrive db 0
kernel_addr dw 0x100
read_sectors db 0x04
putstr:
lodsb ; load the next character
or al,al ; if al = 0 (= character)
jz short putstrd ; return
mov ah, 0x0E ; function 0x0E (display character)
mov bh, 0x00 ; current page
mov bl, 0x07 ; color
int 0x10 ; call display interrupt
jmp putstr
putstrd:
ret
check_cpu:
; i left this out because the message was too long
.386
enable_a20:
cli ; disable interrupts
call wait_key_buf ; wait for kbd buffer to clear
mov al,0xd1 ; tell it we want to write to output port
out 0x64,al
call wait_key_buf ; wait again for kbd to clear
mov al,0xdf ; set desired settings (A20 gate)
out 0x60,al ; send value to data reg
call wait_key_buf ; wait for kbd to clear
mov cx,0x10 ; loop count
kbdwait:
xor ax,ax ; do anything
out 0xe0,ax ; some mor nonsense
loop kbdwait ; loop to waste time
;-------------- check if a20 was enabled --------------
mov al,0xd0
out 0x64,al ; tell kbdc we want to read output port
call wait_key_buf_data ; wait for data to get in it
in al,0x60 ; get it
test al,2 ; test if A20 is on
jnz a20_on ; if it is clear, then it is off
jmp error
a20_on:
ret
wait_key_buf:
xor al,al ; al = 0
in al, 0x64 ; get kbd status
test al, 2 ; is bit 1 clear?
jnz wait_key_buf ; if not wait some more
ret
wait_key_buf_data:
xor cx,cx ; cx = 0
in al, 0x64 ; get kbd status
test al, 1 ; is bit 0 clear?
jz wait_key_buf_data ; if not wait some more
ret
load_kernel:
clc ; clear the carry flag
mov ecx, 5 ; try to reset the driver 5 times
reset_drive:
xor ax, ax ; ax = 0
mov dl, [bootdrive] ; dl = bootdrive
int 0x13 ; reset drive
jnc reset_ok ; if carry flag = 0
loop reset_drive ; else try it again if ecx != 0
jmp error ; if ecx = 0 and the reset always failed, halt
reset_ok:
mov ecx, 5 ; try to read the kernel 5 times
read_kernel:
mov ax, [kernel_addr]
mov es, ax ; address of the buffer
mov ah, 0x02 ; function number 2 (read from disk)
mov al, [read_sectors] ; number of sectors to read
mov dl, [bootdrive] ; set drive
mov dh, 0x00 ; read/write head number
mov ch, 0x00 ; number of the track or cylinder (0 = first)
mov cl, 0x02 ; number of the sector where to start (1 = first)
xor bx, bx ; offset of the buffer
int 0x13
jnc load_ok ; if all is ok return
loop read_kernel ; try once again if there is an error
jmp error ; if ecx = 0 and the read operation always failed, halt
load_ok:
ret
enter_pmode:
cli
lgdt [gdt_desc]
mov eax, cr0 ; enable pmode
or eax, 1
mov cr0, eax
mov eax, DATA_SEL
mov ds, eax
mov es, eax
mov ss, eax
mov ds,eax
mov gs,eax
mov fs,eax
mov ax, STACK_SEL
mov ss,ax
mov esp, 0xFFFF
jmp CODE_SEL:0x1000
cli
hlt
jmp $-2
error:
mov si, msg_failed
call putstr
cli
hlt
jmp $-2
start:
cli
mov [bootdrive], dl ; save the bootdrive
mov ax, 0x9000
mov ss, ax ; setup the stack at 0x9000
mov esp, 0x8000 ; set the stack size
sti
mov ax,0x0000 ; ax = 0
mov es,ax ; correct the segment register
mov ds,ax
call check_cpu
.386
mov si, msg_enable_a20
call putstr
call enable_a20
mov si, msg_ok
call putstr
mov si, msg_load_kernel
call putstr
call load_kernel ; load the kernel
mov si, msg_ok
call putstr
call enter_pmode
cli
hlt
jmp $-2
times 510-($-$$) db 0
db 0x55
db 0xAA
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 10:04 am
by guest
Thank you for looking at the code!
my gdt.inc:
Code: Select all
gdt:
; null descriptor
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; stack descriptor
STACK_SEL equ $-gdt
dw 0xFFFF ; limit 15:0
dw 0x00 ; base 15:0
db 0x00 ; base 23:16
db 0x92 ; access byte: present, ring0, code/data segment, non-executable, non-conforming, writeable, not-accessed
db 0xC0 ; flags: Granularity, 32-bit
db 0x00 ; base 31:24
; data descriptor
DATA_SEL equ $-gdt
dw 0xFFFF ; limit 15:0
dw 0x00 ; base 15:0
db 0x00 ; base 23:16
db 0x92 ; access byte: present, ring0, code/data segment, non-executable, non-conforming, writeable, not-accessed
db 0xC0 ; flags: Granularity, 32-bit
db 0x00 ; base 31:24
; code descriptor
CODE_SEL equ $-gdt
dw 0xFFFF ; limit 15:0
dw 0x00 ; base 15:0
db 0x00 ; base 23:16
db 0x9A ; access byte: present, ring0, code/data segment, executable, non-conforming, readable, not-accessed
db 0xC0 ; flags: Granularity, 32-bit
db 0x00 ; base 31:24
gdt_end:
gdt_desc:
dw gdt_end - gdt - 1 ; GDT limit
dd gdt ; linear address of GDT
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 10:44 am
by frank
kernel_addr dw 0x100
You've loaded your kernel at 0x1000, not 0x100
Change into kernel_addr dw 0x1000
I think the empty character(s) came from
mov si, msg_ok
call putstr
I suppose it has not went into main() 'cause it jumped to 0x100.
I don't know why it hasn't crashed though.. probably cause at 0x100 the first data is empty.
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 11:05 am
by guest
no that's not the problem because in real mode the address is 0x100 in protected mode 0x1000. if i jmp to CODE_SEL:0x100 the cpu crashes
Re:kernel problem (C Pointer)
Posted: Sat Jan 31, 2004 11:28 am
by frank
no that's not the problem because in real mode the address is 0x100 in protected mode 0x1000.
segmented (real mode address) is basically the same as linear addresseses in protected mode when paging is not enabled.
So 0x1000 is 0x1000
0x100 is 0x100
Change it into dw 0x1000
Code: Select all
if i jmp to CODE_SEL:0x100 the cpu crashes
Correct, 'cause your kernel should be loaded at 0x1000, you'll have to jump to 0x1000
Have a look at
http://my.execpc.com/~geezer/osd/ram/
The free memory starts at 0x500