Page 1 of 2
kernel, when i pass a string, pc reboot [c++] *SOLVED*
Posted: Sun Jul 09, 2006 1:10 pm
by origin of
hi all
i'm italian, so, my english is poooor !!
i've a problem...a big problem....
well, this is my code:
video.cpp
Code: Select all
//Video.cpp
#include "video.h"
Video::Video()
{
pos=0 ; off=0 ;
videomem = (unsigned short*) 0xb8000 ;
}
Video::~Video() {}
void Video::clear()
{
unsigned int i;
for(i=0; i<80>=80)
{
pos=0 ;
off += 80 ;
}
if(off>=(80*25))
{
clear() ; //should scroll the screen, but for now, just clear
}
videomem[off + pos] = (unsigned char) c | 0x0700 ;
pos++ ;
}
video.h
Code: Select all
//Video.h
#ifndef VIDEO_H
#define VIDEO_H //so we don't get multiple definitions of Video
class Video
{
public:
Video() ;
~Video() ;
void clear() ;
void write(char *cp) ;
void put(char c) ;
private:
unsigned short *videomem ; //pointer to video memory
unsigned int off ; //offset, used like a y cord
unsigned int pos ; //position, used like x cord
}; //don't forget the semicolon!
#endif
kernel.cpp
Code: Select all
//Kernel.cpp
#include "video.h"
int main(void)
{
Video vid ; //local, (global variables need some Run-Time support code)
vid.put('p');
vid.write("hi all") ;
while(1);
}
loader.asm
Code: Select all
; Loader.asm
[BITS 32] ; protected mode
[global start]
[extern main] ; this is in our C++ code
start:
call main ; call int main(void) from our C++ code
cli ; interrupts could disturb the halt
hlt ; halt the CPU
link.ld
Code: Select all
/* Link.ld */
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
.text 0x100000 :
{
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data :
{
data = .; _data = .; __data = .;
*(.data)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
well, i compile those with
i compile c++ source with -nostdlib -fno-builtin -fno-rtti -fno-exceptions
and link them with -Tlink.ld
look the Kernel.cpp, the instruction vid.put('p'); work, but the instruction vid.write("hi all"); does not work (i have the reboot of pc).
now look video.cpp, and function write, I thought in an error in the cycle (for) so i try to comment all like this
Code: Select all
void Video::write(char *cp)
{
// char *str = cp, *ch;
// for (ch = str; *ch; ch++) put(*ch);
}
but, the pc reboot....so i think that c++ does not accept string ??
remember that i'm italian, my english....is poor !!
can anyone help me ??
or
anyone can help me ??
Posted: Sun Jul 09, 2006 3:05 pm
by JAAman
does not work (i have the reboot of pc).
if your tripple-faulting (normally this causes the computer to reboot), its normally caused by an improper IDT
if your IDT is properly implemented, there should never be a tripple-fault, (an exception will occur instead)
if you dont have an IDT yet, more information will be required (your operating conditions and GDT information would be helpful)
Posted: Sun Jul 09, 2006 3:46 pm
by origin of
i dont't undertand, what is IDT ?
if is necessary, this is my bootloader...where i enter in 32 bit mode and where i do the gdt...
Code: Select all
%include "DK.inc"
[BITS 16] ;16 Bit
[ORG 0x7C00] ;Indirizzo da dove parte il bootloader
xor ax, ax
mov ds, ax
mov ss, ax
mov sp, 0xFFFF
mov si, BOOT ;Open Source Operative System
call print
mov si, KERNEL ;Caricamento Kernel
call print
call load_kernel ;Carico il kernel in memoria ma aspetto a lanciarlo
;Spengo il floppy disk
mov dx, 0x3F2
mov al, 0xC
out dx, al
;Disabilito gli interrupt non mascherabili
in al, 0x70
or al, 0x80
out 0x70, al
;Abilito la linea A20 per poter utilizzare piu memoria
wait1:
in al, 0x64
test al, 0x2
jnz wait1
mov al, 0xD1
out 0x64, al
wait2:
in al, 0x64
and ax, byte 0x2
jnz wait2
mov al, 0xDF
out 0x60, al
;Carico la tabella GDT
lgdt [gdtinfo]
mov eax, CR0
or al, 0x1
mov CR0, eax
;Salto al codice a 32 BIT
jmp dword (flat_code-gdt_table):lancia_kernel
[BITS 16]
print:
lodsb
or al, al
jz .end
mov ah, 0xE
mov bx, 0x7
int 0x10
jmp print
.end:
ret
load_kernel:
mov di, DK ;Dimensione del kernel in settori
mov ax, 0x1000 ;Imposto ax a 0x1000
mov es, ax ;Numero del segmento
xor ch, ch ;Numero della traccia
mov cl, 0x2 ;Numero del settore
xor dl, dl ;Numero della testina
xor dh, dh ;Numero del drive
xor bx, bx ;Azzero il buffer es:bx = 0x1000:0 = Primo Mega
leggi:
mov ah, 0x2 ;Numero del servizio
mov al, 0x1 ;Numero di settori da leggere
int 0x13 ;Esegue la lettura
jc fdc_error ;Gestisci l'eventuale errore
mov ax, es ;Metto il valore di es in ax
add ax, 0x20 ;Modifico il valore di ax
mov es,ax ;Riaggiorno il valore di es
dec di ;Decrementiamo di uno il numero dei settori
jz end ;Se non vi sono più settori, termina
inc cx ;Incremento il numero del settore
cmp cl, 0x12 ;Comparo cl al valore 0x12 (18)
jna leggi ;Se cl è <di>15
dw 0x0000 ;Base bit 0->15
db 0x00 ;Base bit 16->23
db 0x9A ;Segmento codice con privilegio 0
db 0xCF ;Limite bit 16->19 segmento a 32 bit step: 4096 byte
db 0x00 ;Base 24->32
flat_data:
dw 0xFFFF ;Limite bit 0->15
dw 0x0000 ;Base bit 0->15
db 0x00 ;Base bit 16->23
db 0x92 ;Segmento dati con privilegio 0
db 0xCF ;Limite bit 16->19 segmento a 32 bit step: 4096 byte
db 0x00 ;Base 24->32
gdtlength equ $ - gdt_table ;Dimensione della GDT
[BITS 32] ;Codice a 32 bit
lancia_kernel:
mov ax, flat_data - gdt_table
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x9FFF0 ;Imposto lo stack
;Lancio il kernel
push dword 0x2 ;Azzero gli EFLAGS
popfd ;Imposto gli EFLAGS
mov eax, 0x10000 ;Imposta la locazione di memoria del kernel
jmp eax ;Eseguo il kernel
;Messaggi da stampare a video
BOOT db '-- OPEN SOURCE OPERATIVE SYSTEM --', 0xD, 0xA, 0x0
KERNEL db 'Caricamento del kernel', 0xD, 0xA, 0x0
FDC_ERROR db 'Errore nella lettura del floppy', 0xD, 0xA, 0x0
;Azzera i byte rimanenti del bootsecto e metto la word 0xAA55 in fondo
times 510-($-$$) db 0
dw 0xAA55
Posted: Sun Jul 09, 2006 4:02 pm
by JAAman
well, if you dont know what the IDT is, you need to go back and read the manuals again
the IDT controls what the CPU does when an interupt occurs (hard, soft, or firm)
if you have not set an IDT, then as soon as you switch into PMode, the CPU will be unable to handle interupts -- and if you havent disabled hard-ints, you will get one ~18.2 times per second -- the CPU will try to fetch the discriptor from the IDT, being unable to do so, it will trigger a double-fault (handled with interupt#8 ) -- when it cannot execute the double-fault handler, it will enter an invalid state, commonly refered to as a tripple-fault -- most computers will handle this by reseting
i suggest reading the intel manuals, volume 3a, chapter 5 for more information
if you dont have the intel manuals, get them right away -- and read volume 3a through before continuing -- they can be downloaded (and ordered free) at the link in my signature
ps. as i understand, they are availible in several other languages, if you can call the contact number to order the hard copies, i think they can provide them in italian
Posted: Sun Jul 09, 2006 4:18 pm
by earlz
i dont't undertand, what is IDT ?
Then you must not have one
IDT is what handles interrupts and exceptions, exceptions happen when you make an error, usually anyway, like when you divide by 0 you get an exception but if there is no idt then the pc don't know what to do so it just reboots
btw
if your IDT is properly implemented, there should never be a tripple-fault, (an exception will occur instead)
unless you have a stack overflow at the kernel level or the gdt gets messed up
Re: kernel, when i pass a string, pc reboot [c++]
Posted: Sun Jul 09, 2006 6:35 pm
by carbonBased
origin of wrote:
the instruction vid.put('p'); work, but the instruction vid.write("hi all"); does not work (i have the reboot of pc).
Pretty much every time I see this (and it appears to be a frequent issue, so we should perhaps consider adding this to a FAQ on the Wiki?) it's because the GDT is not properly setup.
If you look at the assembly produced by the above statements, I'll bet you 'p' is a constant, and "hi all" is a pointer to your data segment... leading me to believe your data segment descriptor isn't 100% correct.
I did a (very quick) skim of the code, and noticed your load:
lgdt [gdtinfo]
But when I searched for gdtinfo, I couldn't find it. Could you post this portion?
Forgive me if it's there... I didn't do an overly extensive search
Cheers,
Jeff
Re: kernel, when i pass a string, pc reboot [c++]
Posted: Mon Jul 10, 2006 1:49 am
by origin of
carbonBased wrote:origin of wrote:
the instruction vid.put('p'); work, but the instruction vid.write("hi all"); does not work (i have the reboot of pc).
Pretty much every time I see this (and it appears to be a frequent issue, so we should perhaps consider adding this to a FAQ on the Wiki?) it's because the GDT is not properly setup.
If you look at the assembly produced by the above statements, I'll bet you 'p' is a constant, and "hi all" is a pointer to your data segment... leading me to believe your data segment descriptor isn't 100% correct.
I did a (very quick) skim of the code, and noticed your load:
lgdt [gdtinfo]
But when I searched for gdtinfo, I couldn't find it. Could you post this portion?
Forgive me if it's there... I didn't do an overly extensive search
Cheers,
Jeff
i know what is IDT, but i every call it "tabella dei descrittori di interrupt", in in italian....xD
ok,
thakns for help...
this is my gdtinfo:
Code: Select all
gdtinfo:
dw gdtlength ;Numero di elementi presenti nella GDT
dw gdt_table ;Indirizzo della GDT
gdt_table:
dd 0 ;Il primo elemento è nullo
dd 0 ;Il primo elemento è nullo
flat_code:
dw 0xFFFF ;Limite bit 0->15
dw 0x0000 ;Base bit 0->15
db 0x00 ;Base bit 16->23
db 0x9A ;Segmento codice con privilegio 0
db 0xCF ;Limite bit 16->19 segmento a 32 bit step: 4096 byte
db 0x00 ;Base 24->32
flat_data:
dw 0xFFFF ;Limite bit 0->15
dw 0x0000 ;Base bit 0->15
db 0x00 ;Base bit 16->23
db 0x92 ;Segmento dati con privilegio 0
db 0xCF ;Limite bit 16->19 segmento a 32 bit step: 4096 byte
db 0x00 ;Base 24->32
gdtlength equ $ - gdt_table ;Dimensione della GDT
is correct ?
Re: kernel, when i pass a string, pc reboot [c++]
Posted: Mon Jul 10, 2006 8:31 am
by chase
origin of wrote:
this is my gdtinfo:
Code: Select all
gdtinfo:
dw gdtlength ;Numero di elementi presenti nella GDT
dw gdt_table ;Indirizzo della GDT
gdt_table:
dd 0 ;Il primo elemento è nullo
dd 0 ;Il primo elemento è nullo
flat_code:
dw 0xFFFF ;Limite bit 0->15
dw 0x0000 ;Base bit 0->15
db 0x00 ;Base bit 16->23
db 0x9A ;Segmento codice con privilegio 0
db 0xCF ;Limite bit 16->19 segmento a 32 bit step: 4096 byte
db 0x00 ;Base 24->32
flat_data:
dw 0xFFFF ;Limite bit 0->15
dw 0x0000 ;Base bit 0->15
db 0x00 ;Base bit 16->23
db 0x92 ;Segmento dati con privilegio 0
db 0xCF ;Limite bit 16->19 segmento a 32 bit step: 4096 byte
db 0x00 ;Base 24->32
gdtlength equ $ - gdt_table ;Dimensione della GDT
is correct ?
The "gdtinfo" should be either 5 or 6 bytes depending on whether you are doing a 32 or 16 bit lgdt instruction(usually 6).
Intel IA-32 Architecture Software Developers Manual Vol 2A wrote:The source operand specifies a 6-byte memory location
that contains the base address (a linear address) and the limit (size of table in bytes) of the
global descriptor table (GDT) or the interrupt descriptor table (IDT). If operand-size attribute is
32 bits, a 16-bit limit (lower 2 bytes of the 6-byte data operand) and a 32-bit base address (upper
4 bytes of the data operand) are loaded into the register. If the operand-size attribute is
16 bits, a 16-bit limit (lower 2 bytes) and a 24-bit base address (third, fourth, and fifth byte) are
loaded.
I'd also suggest doing your cli before your call to main and after you hlt instruction I'd make an infinite loop back to the hlt instruction.
Do you actually have a IDT ("tabella dei descrittori di interrupt") setup pointing to valid handler code?
The fact that this happens even when you have all your code commented out in the write method makes me thinking it's a problem with your stack segement instead of your data segement. But since you're using the same descriptor for both I guess you could still say it's a problem with your data segment. My wild guess is that your put method might work and your write method might fail just because of how your compiler is optimizing the assembly combined with how your segments are setup. What compiler and version are you using?
Posted: Mon Jul 10, 2006 8:44 am
by origin of
Do you actually have a IDT ("tabella dei descrittori di interrupt") setup pointing to valid handler code?
i don't know this...
but...i compile with gcc o g++ version 4.0.3
and linking with ld version 2.16.91
on linux...
the options i give to g++ are -nostdlib -fno-builtin -fno-rtti -fno-exceptions
and for the linker (ld) is -Tlink.ld, link.ld is in one of my reply...
but it is strange....vid.putc('a'); work, and vid.write("aa"); doesn't work....is strange...i also use the same GDT and the same link.ld, and the same bootloader for another kernel (in c language) which work with the string with the same method....
uff....
Posted: Mon Jul 10, 2006 9:14 am
by chase
origin of wrote:
Do you actually have a IDT ("tabella dei descrittori di interrupt") setup pointing to valid handler code?
i don't know this...
Don't know if you are doing this or don't know what I'm asking?
Try doing "cli" before going to PMode and see if that helps.
You might have to compile to assembly with the -S option to see what the important difference is bewteen the put and the write methods(make them both do nothing). If you do that you might also want to use -masm=intel -finhibit-size-directive -fverbose-asm (which I know work on gcc 3.4)
Posted: Mon Jul 10, 2006 10:05 am
by origin of
chase wrote:origin of wrote:
Do you actually have a IDT ("tabella dei descrittori di interrupt") setup pointing to valid handler code?
i don't know this...
Don't know if you are doing this or don't know what I'm asking?
The first..
Try doing "cli" before going to PMode and see if that helps.
You might have to compile to assembly with the -S option to see what the important difference is bewteen the put and the write methods(make them both do nothing). If you do that you might also want to use -masm=intel -finhibit-size-directive -fverbose-asm (which I know work on gcc 3.4)
I try to put cli before pmode....but...
, is the same...
option -S doesn't exist in nasm....
and if i want to compyle with masm my bootloader, i've to change everything...
Posted: Mon Jul 10, 2006 10:11 am
by chase
origin of wrote:
option -S doesn't exist in nasm....
and if i want to compyle with masm my bootloader, i've to change everything...
-S and those other options are for your C/C++ compiler. They make your C/C++ into assembly language source code instead of binary or object files. You'd also want to use -o to specify the output filename. That way you can read the assembly produced by the compiler and see better what is happening during the reboot.
Posted: Mon Jul 10, 2006 10:56 am
by rexlunae
origin of wrote:chase wrote:origin of wrote:
i don't know this...
Don't know if you are doing this or don't know what I'm asking?
The first..
You would know if you had created an IDT. It isn't something the compiler is likely to do for you. I think the first step is to create one. There may still be other problems with your code, but not having an IDT <i>will</i> cause problems like this one. You should always have an IDT before interrupts are enable, otherwise, the first interrupt will cause a tripple fault and the computer will reboot. If you define an IDT, and put in a handler which can report unexpected exceptions, it may give you much better information to work from.
Posted: Mon Jul 10, 2006 11:13 am
by origin of
@chase && rexlunae :
ok, but the problem whre is ??
in the GDT ??
but IDT isn't created by bios at the boot of pc ??
@rexlunae
If you define an IDT, and put in a handler which can report unexpected exceptions, it may give you much better information to work from.
how i define IDT and put it in a handler ??
i found this
http://www.mega-tokyo.com/osfaq/Help!%2 ... 20crashed! but i can't understand...
if you help me...i promis to you the next world-wide (world-wide traduced by google
, w italia..
Posted: Mon Jul 10, 2006 12:53 pm
by chase
The BIOS provides a real mode IDT. In PMode you have to provide everything such as an IDT and the interrupt handling code. But if you do a cli before you start PMode and don't do a sti then your current problem shouldn't be related to the IDT stuff.