kernel, when i pass a string, pc reboot [c++] *SOLVED*

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
origin of
Member
Member
Posts: 27
Joined: Sun Jul 09, 2006 2:35 am

kernel, when i pass a string, pc reboot [c++] *SOLVED*

Post 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 !! :D

can anyone help me ??
or :roll:
anyone can help me ??
Last edited by origin of on Tue Jul 11, 2006 8:44 am, edited 1 time in total.
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post 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)
origin of
Member
Member
Posts: 27
Joined: Sun Jul 09, 2006 2:35 am

Post 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
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post 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
Last edited by JAAman on Sun Jul 09, 2006 5:44 pm, edited 1 time in total.
earlz
Member
Member
Posts: 1546
Joined: Thu Jul 07, 2005 11:00 pm
Contact:

Post 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
User avatar
carbonBased
Member
Member
Posts: 382
Joined: Sat Nov 20, 2004 12:00 am
Location: Wellesley, Ontario, Canada
Contact:

Re: kernel, when i pass a string, pc reboot [c++]

Post 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
origin of
Member
Member
Posts: 27
Joined: Sun Jul 09, 2006 2:35 am

Re: kernel, when i pass a string, pc reboot [c++]

Post 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 ? :oops:
User avatar
chase
Site Admin
Posts: 710
Joined: Wed Oct 20, 2004 10:46 pm
Libera.chat IRC: chase_osdev
Location: Texas
Discord: chase/matt.heimer
Contact:

Re: kernel, when i pass a string, pc reboot [c++]

Post 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 ? :oops:
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?
origin of
Member
Member
Posts: 27
Joined: Sun Jul 09, 2006 2:35 am

Post 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.... :cry:
User avatar
chase
Site Admin
Posts: 710
Joined: Wed Oct 20, 2004 10:46 pm
Libera.chat IRC: chase_osdev
Location: Texas
Discord: chase/matt.heimer
Contact:

Post 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)
origin of
Member
Member
Posts: 27
Joined: Sun Jul 09, 2006 2:35 am

Post 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... :cry: , 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...
User avatar
chase
Site Admin
Posts: 710
Joined: Wed Oct 20, 2004 10:46 pm
Libera.chat IRC: chase_osdev
Location: Texas
Discord: chase/matt.heimer
Contact:

Post 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.
rexlunae
Member
Member
Posts: 134
Joined: Sun Oct 24, 2004 11:00 pm
Location: North Dakota, where the buffalo roam

Post 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.
origin of
Member
Member
Posts: 27
Joined: Sun Jul 09, 2006 2:35 am

Post 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.. :twisted:
User avatar
chase
Site Admin
Posts: 710
Joined: Wed Oct 20, 2004 10:46 pm
Libera.chat IRC: chase_osdev
Location: Texas
Discord: chase/matt.heimer
Contact:

Post 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.
Post Reply