Asembler + C -> Bootloader, Jądro systemu, Błąd podczas wywołania funkcji.

0

Witam.
Mam dość nietypowy problem z którym nie mogę sobie poradzić. Mianowicie piszę bootloader + proste jądro systemu w c w którym docelowo chcę zrobić prymitywną konsolę. Bootloader wyświetla powitanie, odblokowuje A20, ładuję tablicę gdt, ładuje plik jądra, przechodzi w tryb chroniony a następnie przekazuje sterowanie do jądra systemu.
W moim prymitywnym jądrze mam zrobiony bufor do wypisywania tekstu na ekran. Wszystko działa ok, ale niestety tylko gdy 1 raz wykonam funkcję print(tablica). Przy kolejnym wykonaniu cały "system" się wysypuje. W QEMU wyskakuje mi naruszenie pamięci. Co ciekawe gdy zrobię for(i=0; i<20; i++) print(tablica), to ładnie wypisze mi 20 napisów na ekranie. Przy próbie wypisania kolejnego napisu (wywołania funkcji print) na ekranie pojawia się tylko litera "S" a po jakimś czasie wyskakuje naruszenie pamięci.
Myślę, że problem jest ze stosem przy 2 wywołaniu funkcji. Gdy sprawdzałem stos po 2 wywołaniu to niestety był pusty...

Kod bootloadera:

[ORG 0x7C00]
[BITS 16]

bootloader:

	xor 	ax, ax
	mov 	ds, ax

	mov 	si, msg
	call 	_showTekst		; wyswietlenie powitania "witaj w bootloaderze"

;************************ Wczytanie jadra systemu ******************

	mov	si, read_pocket
	mov	ah, 0x42	; extension
	mov	dl, 0x80	; drive number (0x80 should be drive #0)
	int	0x13


;_halt: 	jmp _halt
	jmp _odblokowanieA20
;********************* Odblokowanie A20 ****************************

_sprawdzA20:

	mov	ax, 0xFFFF
	mov	es, ax
	mov	di, 0x7E0E
	mov	al, byte[es:di]
	cmp	al, 0x55		; comparing with 0x55 (first part)
	jne	_wys

	mov	si, msgA20dis
	call	_showTekst	
ret

_odblokowanieA20:

	call	_sprawdzA20		; sprawdzenie czy przypadkiem A20 nie jest aktywne
; za pomoca biosu
	mov	ax, 0x2401
	int 	0x15
	call	_sprawdzA20	

; za pomoca kontrolera klawiatury
	call	_waitA20
	mov 	al, 0xD1
	out	0x64, al
	call	_waitA20
	mov	al, 0xDF
	out	0x60, al
	call	_waitA20
	
	call	_sprawdzA20

_waitA20:
	in 	al, 0x64
	test	al, 2
	jnz	_waitA20
	ret

;**********************************************************************

;********************** Funkcja wyswietlajaca tekst ****************

_showTekst:

	mov	ah, 0x0E
	mov  	bh, 0x00
	mov	bl, 0x07

  _wypisz:
	lodsb
	or	al, al
	jz	_koniecWypisz
	int 	0x10
	jmp	_wypisz
 _koniecWypisz:

ret

;******************** Wyswietlenie, że a20 jest aktywna **********

_wys:
	mov	si, msgA20enb
	call	_showTekst

; Uruchomienie tryby chronionego
	cli
	lgdt 	[_gdtDesc]
	mov 	eax, cr0
	or 	eax, 1
	mov 	cr0, eax
	jmp 	0x8:clear_pipe	; do the far jump, to clear instruction pipe

;*************** GDT ***********************************************

_gdt:
_gdtNull:
	dq	0		; it's just null..
_gdtCode:
	dw 	0xFFFF		; limit (4GB)
	dw	0		; base (0)
	db	0		; base (still 0)
	db	10011010b	; [present][privilege level][privilege level][code segment][code segment][conforming][readable][access]
	db	11001111b	; [granularity][32 bit size bit][reserved][no use][limit][limit][limit][limit]
	db 	0		; base again
_gdtData:
   	dw	0xFFFF		; it's just same as above
   	dw	0		; it's just same as above
	db	0		; it's just same as above
	db	10010010b	; [present][privilege level][privilege level][data segment][data segment][expand direction][writeable][access]
	db 	11001111b	; it's just same as above
	db 	0		; it's just same as above
_gdtEnd:

_gdtDesc:
   	dw 	_gdtEnd - _gdt	; it's size
   	dd	_gdt		; and location




;******************* tryb 32 bitowy chroniony ********************

[BITS 32]
clear_pipe:

	mov	ax, 0x10	; GDT address of data segment
	mov	ds, ax		; set data segment register
	mov	ss, ax		; set stack segment register
	xor	edx, edx
	mov	fs, dx
	mov	gs, dx
	mov	esp, 0xF0000	; set stack
	mov	ebp, esp	; set bracket pointer
	jmp	0xF000		; jump to code
	times 256-($-$$) db 0	; fill rest with zeros for alignment
;*******************************************************************

;********************** Zmienne ************************************
msgA20enb: 
	db	'A20 -> enable',13,10,0
msgA20dis: 
	db	'A20 -> disable',13,10,0
msg: 
	db	'Witamy w bootloaderze', 13,10,0

read_pocket:
	db	0x10		; size of pocket
	db	0		; const 0
	dw	10		; number of sectors to transfer
	dw	0xF000, 0x0000	; address to write
	dd	1		; LBA
	dd	0		; upper LBA 

times 510-($-$$) db 0	; wypenienie niewykorzystanej przestrzeni 0
db 0x55	
db 0xAA			; ostatnie 2 bajty musza miec wartosci AA, 55


Kod systemu:



static char bufor[25][80];
volatile char *videos = (volatile char*)0xB8000;


static void zeruj(){

	int i,j;
	for( i=0; i<25; i++)
		for( j=0; j<80; j++)
		bufor[i][j] = ' ';

}

static void przepisz(){
	
	int i = 0;
	int j = 0;

	for(i=1; i<25; i++)
		for( j=0; j<80; j++)
		bufor[i-1][j] = bufor[i][j];

	for(i=0; i<80; i++)
		bufor[24][i] = ' ';

}

static void wypisz(){

	
	volatile char *video = (volatile char*)0xB8000;
	
	int i = 0;
	int j = 0;

	for(i=0; i<25; i++){

		for(j=0; j<80; j++){
		 
		*video++ = bufor[i][j];
        	*video++ = 0x07;
  		}

	}

}

static void print(char *tab){

	przepisz();
	int i = 0;

	for(i=0; i<80; i++)
	{
		if(tab[i] == 0)
			break;

		bufor[24][i] = tab[i];
	}

	wypisz();
}


void main(void)
{
	
	char test[] = "Przykladowy ttt 1";	
	char aaa[] = "Przykladowy tekst 2";
	
for(i=0; i<20; i++)
	print(aaa);

        print(aaa);                    // ERROR pamieci.

	while(1);
};

 

Kompiluję to poleceniami:

nasm boot.asm -f bin -o ./bin/boot.bin
gcc -c kernel.c -O2 -o ./bin/kernel.o -m32 -nostdlib -nostartfiles -nodefaultlibs

Proszę o jakieś sugestie jak rozwiązać mój problem.
Z góry dziękuję za każdą wskazówkę.
Pozdrawiam.

0

Nie podałeś jak to nagrywasz i jak odpalasz.
Co jest pod adresem F000, że tam skaczesz? plik .o?

Oprócz tego:

  • nie ustawiasz przerwań
  • nie inicjalizujesz PIC
    więc komputer nadal jest w stanie niepełnosprawnym pod instrukcją cli.

jak wygląda stos przed i po wywołaniu print? nie że „jest pusty”, tylko czy ss i esp wynoszą tyle samo przed i po?

0

Dzięki za odpowiedź.

Tak pod adresem 0xF000 jest plik kernel.o. Podam skrypt linkera oraz Makefile.

Linker:

 
OUTPUT_FORMAT("binary")
OUTPUT_ARCH ("i386")
ENTRY (main)
 
SECTIONS
{
	. = 0xF000;
	 
  	.text : {
        	*(.text)
    	}
 
	.rodata ALIGN (0x1000) : {
        	*(.rodata)
    	}
 
	.data ALIGN (0x1000) : {
       		*(.data)
	}
 
    	.bss : {
		*(.bss)
    	}
}

Makefile:

 

run: image
	qemu -hda ./bin/boot.img

prepare:
	mkdir -p bin

bootloader: prepare boot.asm
	nasm boot.asm -f bin -o ./bin/boot.bin
	gcc -c kernel.c -O2 -o ./bin/kernel.o -m32 -nostdlib -nostartfiles -nodefaultlibs
	ld -T linker.ld -o ./bin/kernel.bin ./bin/kernel.o
	dd if=/dev/zero of=./bin/zeros bs=1  count=500

image: bootloader
	cat ./bin/boot.bin ./bin/kernel.bin ./bin/zeros > ./bin/boot.img

clean:
	rm -rf ./bin/*

W załącznikach dodałem ekran po wywołaniu 2x funkcji print, wartości rejestrów, oraz wyświetlona pamięć stosu.

0

po co tak komplikujesz kod z tym przepisz() i wypisz() zamiast pisać od razu na ekran?

0

No może trochę przekombinowane, ale problem jest z przekazaniem wartości do funkcji...
Docelowo chciałbym aby ten bufor był większy niż 25 linii. Następnie mógłbym w łatwy sposób zrobić przewijanie poprzednio wyświetlonego tekstu.

0
czornexxx napisał(a):
_gdtDesc:
   	dw 	_gdtEnd - _gdt	; it's size
   	dd	_gdt		; and location

Czy to nie powinno być czasem:

_gdtDesc:
   	dw 	_gdtEnd - _gdt - 1
   	dd	_gdt

?

0

Nie, powinno być

dw     _gdtEnd - _gdt - 1    ; its size

jak kiedyś pisałem OS-a pod NASM-em, najpierw zdefiniowałem sobie makra do generowania wpisów GPT i innych struktur, tak że potem mogłem je łatwo zmieniać bez obliczania bajtów i koszmarków typu

db    11001111b    ; [granularity][32 bit size bit][reserved][no use][limit][limit][limit][limit]
0

Z -1 bądź bez efekt ten sam...

Edit.
Ma ktoś jeszcze jakiś pomysł jak sobie z w/w problemem poradzić?

0

możesz skorzystać z gruba przecież ma kod otwarty więc można modyfikować.

0

Ok dzięki za podpowiedź.
Generalnie zależy mi na tym abym sam napisał bootloader.

Poeksperymentowałem dzisiaj i sprawa wygląda tak:

  • Jak w funkcji printf za komentuję wywołanie funkcji przepisz, oraz wypisz.
    -> A w funkcji main() wywołam:
    przepisz();
    printf("jakis_tekst")
    wypisz();
    to takich 3 funkcji mogę wykonywać dowolną ilość razy i wszystko działa poprawnie, a gdy staram się wywołać z funkcji funkcję to wywala błędy takie jak wyżej opisałem.

W czym może być problem?

0
jmp    0xF000        ; jump to code

Skaczesz tutaj do kodu, ale nikt nie powiedział, że będzie to kod funkcji main. To, że w określonych warunkach kernel się nie wywala to czysty przypadek.

Generalnie odradzam wykorzystywać pliki binarne, bo same z nimi kłopoty. Spróbuj zaimplementować chociaż najprostszą obsługę ELFów. Na początku może trochę więcej pracy, ale naprawdę warto.

0

Mógłby ktoś podesłać jakieś info jak zaimplementować obsługę tych ELFów?.
lukasz1235: Miałeś racje, że to działa jak chce. Nazwę main mogę zmienić na cokolwiek i nadal program działa...

0

Mimo wszystko, chyba lepiej tę obsługę ELFa (czy dowolnego podobnego formatu) pisać jednak w C niż asemblerze, tylko trzeba mieć działające C najpierw.

Pokaż jak twój kod w C wygląda po dezasemblacji.
np. ndisasm kernel.bin

0

Generalnie teraz sprawa wygląda tak.
Znalazłem na necie sposób aby zrobić plik entry.asm i przez niego wywoływać funkcje w c.

entry.asm:

[BITS 32]

[EXTERN k_main]

	call	k_main		
	hlt		

kernel.c

 
char bufor[25][80];


void zeruj(){

	int i,j;
	for( i=0; i<25; i++)
		for( j=0; j<80; j++)
		bufor[i][j] = ' ';

}

void przepisz(){
	
	int i = 0;
	int j = 0;
	int c;

	for(i=1; i<25; i++){
		for( j=0; j<80; j++){
		   bufor[i-1][j] = bufor[i][j];
		}
	}

	for(c=0; c<80; c++){

		bufor[24][c] = ' ';
	}

}

void wypisz(){

	
	volatile char *video = (volatile char*)0xB8000;
	
	int i = 0;
	int j = 0;

	for(i=0; i<25; i++){

		for(j=0; j<80; j++){
		 
		*video++ = bufor[i][j];
        	*video++ = 0x07;
  		}

	}

}


void print(char *tab){

	int i = 0;
	int j = 0;

	przepisz();

	for(i=0; i<80; i++)
	{
		if(tab[i] == 0)
			break;
		
		bufor[24][i] = tab[i];
	}

	wypisz();
}

void k_main(void)	
{
	
	print("To jest pierwszy tekst");
	print("Linia nr 2");

	while(1); /* just spin */
}

Kompiluję to za pomocą takiego skryptu:

run: image
	qemu -hda ./bin/boot.img

prepare:
	mkdir -p bin

bootloader: prepare boot.asm
	nasm entry.asm -f coff -o ./bin/entry.o
	nasm boot.asm -f bin -o ./bin/boot.bin
	gcc -c kernel.c -O2 -o ./bin/kernel.o 
	ld -T linker.ld -o ./bin/kernel.bin ./bin/entry.o ./bin/kernel.o
	dd if=/dev/zero of=./bin/zeros bs=1  count=500

image: bootloader
	cat ./bin/boot.bin ./bin/kernel.bin ./bin/zeros > ./bin/boot.img

clean:
	rm -rf ./bin/*

 

Po wykonaniu polecenia: ndisasm kernel.bin

00000000  E84601            call word 0x149
00000003  0000              add [bx+si],al
00000005  F4                hlt
00000006  6690              xchg eax,eax
00000008  6690              xchg eax,eax
0000000A  6690              xchg eax,eax
0000000C  6690              xchg eax,eax
0000000E  6690              xchg eax,eax
00000010  31D2              xor dx,dx
00000012  8DB60000          lea si,[bp+0x0]
00000016  0000              add [bx+si],al
00000018  31C0              xor ax,ax
0000001A  8DB60000          lea si,[bp+0x0]
0000001E  0000              add [bx+si],al
00000020  C6840240B2        mov byte [si+0x4002],0xb2
00000025  0000              add [bx+si],al
00000027  2083C001          and [bp+di+0x1c0],al
0000002B  83F850            cmp ax,byte +0x50
0000002E  75F0              jnz 0x20
00000030  83C250            add dx,byte +0x50
00000033  81FAD007          cmp dx,0x7d0
00000037  0000              add [bx+si],al
00000039  75DD              jnz 0x18
0000003B  F3C3              rep ret
0000003D  8D7600            lea si,[bp+0x0]
00000040  53                push bx
00000041  B95000            mov cx,0x50
00000044  0000              add [bx+si],al
00000046  6690              xchg eax,eax
00000048  31C0              xor ax,ax
0000004A  8D59B0            lea bx,[bx+di-0x50]
0000004D  8D7600            lea si,[bp+0x0]
00000050  0FB6940140        movzx dx,[si+0x4001]
00000055  B200              mov dl,0x0
00000057  00889403          add [bx+si+0x394],cl
0000005B  40                inc ax
0000005C  B200              mov dl,0x0
0000005E  0083C001          add [bp+di+0x1c0],al
00000062  83F850            cmp ax,byte +0x50
00000065  75E9              jnz 0x50
00000067  83C150            add cx,byte +0x50
0000006A  81F9D007          cmp cx,0x7d0
0000006E  0000              add [bx+si],al
00000070  75D6              jnz 0x48
00000072  31C0              xor ax,ax
00000074  8D7426            lea si,[si+0x26]
00000077  00C6              add dh,al
00000079  80C0B9            add al,0xb9
0000007C  0000              add [bx+si],al
0000007E  2083C001          and [bp+di+0x1c0],al
00000082  83F850            cmp ax,byte +0x50
00000085  75F1              jnz 0x78
00000087  5B                pop bx
00000088  C3                ret
00000089  8DB42600          lea si,[si+0x26]
0000008D  0000              add [bx+si],al
0000008F  0056B8            add [bp-0x48],dl
00000092  00800B00          add [bx+si+0xb],al
00000096  53                push bx
00000097  BE40B2            mov si,0xb240
0000009A  0000              add [bx+si],al
0000009C  8D7426            lea si,[si+0x26]
0000009F  008D98A0          add [di-0x5f68],cl
000000A3  0000              add [bx+si],al
000000A5  0089F2EB          add [bx+di-0x140e],cl
000000A9  088DB600          or [di+0xb6],cl
000000AD  0000              add [bx+si],al
000000AF  0089C80F          add [bx+di+0xfc8],cl
000000B3  B60A              mov dh,0xa
000000B5  83C201            add dx,byte +0x1
000000B8  8808              mov [bx+si],cl
000000BA  8D4802            lea cx,[bx+si+0x2]
000000BD  39D9              cmp cx,bx
000000BF  C6400107          mov byte [bx+si+0x1],0x7
000000C3  75EB              jnz 0xb0
000000C5  83C650            add si,byte +0x50
000000C8  81FBA08F          cmp bx,0x8fa0
000000CC  0B00              or ax,[bx+si]
000000CE  89D8              mov ax,bx
000000D0  75CE              jnz 0xa0
000000D2  5B                pop bx
000000D3  5E                pop si
000000D4  C3                ret
000000D5  8D7426            lea si,[si+0x26]
000000D8  008DBC27          add [di+0x27bc],cl
000000DC  0000              add [bx+si],al
000000DE  0000              add [bx+si],al
000000E0  56                push si
000000E1  53                push bx
000000E2  8B5C24            mov bx,[si+0x24]
000000E5  0CE8              or al,0xe8
000000E7  55                push bp
000000E8  FF                db 0xff
000000E9  FF                db 0xff
000000EA  FF31              push word [bx+di]
000000EC  C0EB0E            shr bl,byte 0xe
000000EF  8890C0B9          mov [bx+si-0x4640],dl
000000F3  0000              add [bx+si],al
000000F5  83C001            add ax,byte +0x1
000000F8  83F850            cmp ax,byte +0x50
000000FB  7408              jz 0x105
000000FD  0FB614            movzx dx,[si]
00000100  0384D275          add ax,[si+0x75d2]
00000104  EA31DBBE00        jmp word 0xbe:0xdb31
00000109  800B00            or byte [bp+di],0x0
0000010C  8D7426            lea si,[si+0x26]
0000010F  0089F231          add [bx+di+0x31f2],cl
00000113  C0EB04            shr bl,byte 0x4
00000116  6690              xchg eax,eax
00000118  89CA              mov dx,cx
0000011A  0FB68C0340        movzx cx,[si+0x4003]
0000011F  B200              mov dl,0x0
00000121  0083C001          add [bp+di+0x1c0],al
00000125  83F850            cmp ax,byte +0x50
00000128  880A              mov [bp+si],cl
0000012A  8D4A02            lea cx,[bp+si+0x2]
0000012D  C6420107          mov byte [bp+si+0x1],0x7
00000131  75E5              jnz 0x118
00000133  81C6A000          add si,0xa0
00000137  0000              add [bx+si],al
00000139  83C350            add bx,byte +0x50
0000013C  81FEA08F          cmp si,0x8fa0
00000140  0B00              or ax,[bx+si]
00000142  75CC              jnz 0x110
00000144  5B                pop bx
00000145  5E                pop si
00000146  C3                ret
00000147  89F6              mov si,si
00000149  8DBC2700          lea di,[si+0x27]
0000014D  0000              add [bx+si],al
0000014F  0083EC04          add [bp+di+0x4ec],al
00000153  C704246D          mov word [si],0x6d24
00000157  B100              mov cl,0x0
00000159  00E8              add al,ch
0000015B  81FFFFFF          cmp di,0xffff
0000015F  C7042484          mov word [si],0x8424
00000163  B100              mov cl,0x0
00000165  00E8              add al,ch
00000167  75FF              jnz 0x168
00000169  FF                db 0xff
0000016A  FF                db 0xff
0000016B  EBFE              jmp short 0x16b
0000016D  54                push sp
0000016E  6F                outsw
0000016F  206A65            and [bp+si+0x65],ch
00000172  7374              jnc 0x1e8
00000174  207069            and [bx+si+0x69],dh
00000177  657277            gs jc 0x1f1
0000017A  737A              jnc 0x1f6
0000017C  7920              jns 0x19e
0000017E  7465              jz 0x1e5
00000180  6B737400          imul si,[bp+di+0x74],byte +0x0
00000184  4C                dec sp
00000185  696E696120        imul bp,[bp+0x69],word 0x2061
0000018A  6E                outsb
0000018B  7220              jc 0x1ad
0000018D  3200              xor al,[bx+si]
0000018F  0014              add [si],dl
00000191  0000              add [bx+si],al
00000193  0000              add [bx+si],al
00000195  0000              add [bx+si],al
00000197  0001              add [bx+di],al
00000199  7A52              jpe 0x1ed
0000019B  0001              add [bx+di],al
0000019D  7C08              jl 0x1a7
0000019F  011B              add [bp+di],bx
000001A1  0C04              or al,0x4
000001A3  0488              add al,0x88
000001A5  0100              add [bx+si],ax
000001A7  0010              add [bx+si],dl
000001A9  0000              add [bx+si],al
000001AB  001C              add [si],bl
000001AD  0000              add [bx+si],al
000001AF  0060FE            add [bx+si-0x2],ah
000001B2  FF                db 0xff
000001B3  FF2D              jmp word far [di]
000001B5  0000              add [bx+si],al
000001B7  0000              add [bx+si],al
000001B9  0000              add [bx+si],al
000001BB  0018              add [bx+si],bl
000001BD  0000              add [bx+si],al
000001BF  0030              add [bx+si],dh
000001C1  0000              add [bx+si],al
000001C3  007CFE            add [si-0x2],bh
000001C6  FF                db 0xff
000001C7  FF4900            dec word [bx+di+0x0]
000001CA  0000              add [bx+si],al
000001CC  00410E            add [bx+di+0xe],al
000001CF  08830202          or [bp+di+0x202],al
000001D3  47                inc di
000001D4  C3                ret
000001D5  0E                push cs
000001D6  0400              add al,0x0
000001D8  2000              and [bx+si],al
000001DA  0000              add [bx+si],al
000001DC  4C                dec sp
000001DD  0000              add [bx+si],al
000001DF  00B0FEFF          add [bx+si-0x2],dh
000001E3  FF4500            inc word [di+0x0]
000001E6  0000              add [bx+si],al
000001E8  00410E            add [bx+di+0xe],al
000001EB  08860246          or [bp+0x4602],al
000001EF  0E                push cs
000001F0  0C83              or al,0x83
000001F2  037CC3            add di,[si-0x3d]
000001F5  0E                push cs
000001F6  0841C6            or [bx+di-0x3a],al
000001F9  0E                push cs
000001FA  0400              add al,0x0
000001FC  2000              and [bx+si],al
000001FE  0000              add [bx+si],al
00000200  7000              jo 0x202
00000202  0000              add [bx+si],al
00000204  DCFE              fdiv to st6
00000206  FF                db 0xff
00000207  FF6700            jmp word [bx+0x0]
0000020A  0000              add [bx+si],al
0000020C  00410E            add [bx+di+0xe],al
0000020F  08860241          or [bp+0x4102],al
00000213  0E                push cs
00000214  0C83              or al,0x83
00000216  0302              add ax,[bp+si]
00000218  63C3              arpl bx,ax
0000021A  0E                push cs
0000021B  0841C6            or [bx+di-0x3a],al
0000021E  0E                push cs
0000021F  0410              add al,0x10
00000221  0000              add [bx+si],al
00000223  00940000          add [si+0x0],dl
00000227  0028              add [bx+si],ch
00000229  FF                db 0xff
0000022A  FF                db 0xff
0000022B  FF1D              call word far [di]
0000022D  0000              add [bx+si],al
0000022F  0000              add [bx+si],al
00000231  43                inc bx
00000232  0E                push cs
00000233  08                db 0x08

W QEMU wszystko działa jak należy, ale gdy za pomocą "MagicISO" wczytam plik boot.img jako bootloader i zapiszę plik jako boot.iso a następnie uruchomię w virtualBoxie to wyskakuje mi error.
Log z VB w załączonym pliku.

Generalnie gdyby to działało pod VB tak jak pod QEMU to byłbym zadowolony.

Bardzo dziękuję za wszelką pomoc.

3

Kiepski adres sobie wybrałeś na stos kernela. Spójrz tutaj: http://wiki.osdev.org/Memory_Map_(x86)#Overview
Pamięć od 0x000A0000 do 0x000FFFFF jest "unusable". Przenieś stos pod jakiś wyższy adres, który jest opisany jako "free for use".

0

Dzięki wielkie.
Zmiana adresu stosu na 0xF00000 przyniosła oczekiwany rezultat. Działa pod VB.
Aktualny stan programu mnie satysfakcjonuje, teraz chciałbym uruchomić przerwania i wczytać coś z klawiatury. Mam nadzieję, że mi się uda, jak napotkam problemy to będę pisał.

Bardzo dziękuję za wszystkie informacje.

1

oho, rosną wymagania sprzętowe, teraz trzeba mieć aż 16 MB RAM do tak prymitywnego kernelka ;-)
wiedz też, że trafiłeś akurat na początek tzw. “memory hole” obecnego na niektórych płytach głównych (a możliwego do włączenia w BIOSie). przy włączonym memory hole nie ma RAM-u w obszarze 15MB-16MB. (15MB to akurat koniec twojego stosu, więc powinno być ok, chyba że zachodzi problem “off-by-one” ;-)

A co do przerwań. Musisz zbudować tablicę IDT, napisać sensowną obsługę wyjątków (kilka przerwań o niskich numerach), oraz zainicjalizować układ PIC obsługujący przerwania sprzętowe (IRQ).
Koniecznie musisz ustawić inny niż domyślny adres bazowy IRQ, bo domyślne numery przerwań kolidują z przerwaniami odpowiedzialnymi za wyjątki.

http://wiki.osdev.org/8259_PIC

Klawiatura. Żeby działała z sensem, zaimplementuj cykliczny bufor klawiatury tak, że w przerwaniu zapisujesz tylko kod klawisza do bufora, a odczytu z bufora dokonujesz funkcjami readkey i keypressed.

readkey - czyta znak z bufora, a jeśli ten jest pusty, to czeka na naciśnięcie klawisza.
keypressed - zwraca true jeśli znak jest w buforze.

Łatwo jest zaimplementować cykliczny bufor o rozmiarze 2n. MS-DOS używał chyba rozmiaru 512, ja kiedyś zaimplementowałem mniejszy o rozmiarze 16 znaków i też było OK.

Kody klawiszy wysyłane z klawiatury nie mają nic wspólnego z kodami ASCII tych klawiszy. Poszukaj tablicy scancode'ów klawiatury.

0

Witam, ja również zajmuję się pisaniem prostego kernela. Nie używam GRUBa dlatego większość rzeczy muszę zaimplementować. Problem pojawił się przy przekierowaniu przerwań. Korzystam z funkcji PIC_REMAP:

/* reinitialize the PIC controllers, giving them specified vector offsets
   rather than 8h and 70h, as configured by default */
 
#define ICW1_ICW4	0x01		/* ICW4 (not) needed */
#define ICW1_SINGLE	0x02		/* Single (cascade) mode */
#define ICW1_INTERVAL4	0x04		/* Call address interval 4 (8) */
#define ICW1_LEVEL	0x08		/* Level triggered (edge) mode */
#define ICW1_INIT	0x10		/* Initialization - required! */
 
#define ICW4_8086	0x01		/* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO	0x02		/* Auto (normal) EOI */
#define ICW4_BUF_SLAVE	0x08		/* Buffered mode/slave */
#define ICW4_BUF_MASTER	0x0C		/* Buffered mode/master */
#define ICW4_SFNM	0x10		/* Special fully nested (not) */
 
/*
arguments:
	offset1 - vector offset for master PIC
		vectors on the master become offset1..offset1+7
	offset2 - same for slave PIC: offset2..offset2+7
*/
void PIC_remap(int offset1, int offset2)
{
	unsigned char a1, a2;
 
	a1 = inb(PIC1_DATA);                        // save masks
	a2 = inb(PIC2_DATA);
 
	outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);  // starts the initialization sequence (in cascade mode)
	io_wait();
	outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
	io_wait();
	outb(PIC1_DATA, offset1);                 // ICW2: Master PIC vector offset
	io_wait();
	outb(PIC2_DATA, offset2);                 // ICW2: Slave PIC vector offset
	io_wait();
	outb(PIC1_DATA, 4);                       // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
	io_wait();
	outb(PIC2_DATA, 2);                       // ICW3: tell Slave PIC its cascade identity (0000 0010)
	io_wait();
 
	outb(PIC1_DATA, ICW4_8086);
	io_wait();
	outb(PIC2_DATA, ICW4_8086);
	io_wait();
 
	outb(PIC1_DATA, a1);   // restore saved masks.
	outb(PIC2_DATA, a2);
} 

Jednak nie mogę dojść do tego jakie wartości powinny przyjąć argumenty funkcji. Wstawiałam 0x0...0xF do odpowiednio 0x2...0x2F i w ten sposób nie działa.
Funkcję wywołuję zaraz po wejściu do mojego głównego pliku w c: kernel.c - jest on dokładnie taki sam jak powyższy plik kernel.c

0

Witam po małej przerwie.

Sprawa wygląda następująco. Uporałem się ( przynajmniej tak mi się wydaje ) z przerwaniem klawiatury. Teraz chcę napisać funkcję typu getChar() oraz np. getString(). Chciałbym aby getChar() zwracała naciśniętego chara. Jeśli go nie ma to aby na niego poczekała. getString() po naciśnięciu Enter zwraca tablicę charów z odczytanymi znakami.

Bufor realizuję jako tablica charów kBufor[10].
Wpisywanie do bufora odbywa się poprzez funkcję:

 
void setBuforChar(char znak){	

	if(kIlosc >=9)
		print("Przepelnienei bufora klawiatury!!!");
	else{
	
		kBufor[kIlosc] = znak;
		kIlosc++;
	}

}

W przerwaniu wywołuję setBuforChar(key); Gdzie key to już kod ASCII znaku.

Zaimplementowałem funkcję:

 

char getChar(){	

   char tmp;
   
   while(kIlosc < 1);   

   tmp = kBufor[0];
   kIlosc = 0;
 
return tmp;
}

Teraz pytanie czy poprawnie wykorzystuję bufor ? Generalnie program działa zgodnie z założeniem.
Dlaczego mój system po uruchomieniu zabiera 100% jednego wątka ? Jak to zmienić?
Oraz czy czekanie typu while(kIlosc < 1) jest poprawne? Czy może należy użyć do tego celu jakiegoś timera?

0

Bufor klawiatury powinien być kolejką FIFO.
Poczytaj jak zaimplementować bufor cykliczny.

0

Ale czy to nie będzie to samo jak z tablicy będę odczytywał: kBufor[(kIlosc-1)] i tak aż do odczytania wszystkich elementów? kIlosc = 0?

Czy obsługa dynamicznego alokowania pamięci jest do zrobienia bez stronicowania ?? Np. chciałbym tworzyć w funkcji getString() tablicę char[ rozmiar ], a następnie zwrócić wskaźnik na tę tablicę jako wynik działania funkcji?

1

Zamiast korzystać z własnych sektorów rozruchowych, proponuję link, ładuje plik jądra o nazwie "KERNEL" pod adres fizyczny poza BIOSem 0x100000 i przygotowuje w pełni dostępne środowisko 64 bitowe. Nic tylko pisać własne jądro systemu i nie przejmować się sprawami przyziemnymi ;)

Rany boskie, jak zobaczyłem wynik

ndisasm kernel.bin
takiego prostego programu w C, to mi się włos zjeżył od tej ilości śmieci.

0

Dziękuję za odpowiedź, ale niestety muszę sam napisać bootloader oraz prosty kernel w C.

Myślałem, że z przerwaniami sobie poradziłem ale niestety jednak nie. Działa mi tylko przerwanie od klawiatury, a jak włączę też przerwania timera to system się wysypuje. O ile dobrze odczytałem to wywala wyjątek nr. 7.

W kernelu ładuję: IDT a następnie przekierowuję przerwania następującą funkcją:

void PIC_remap(int offset1, int offset2)
{
	unsigned char a1, a2;
 
	a1 = inb(PIC1_DATA);                        // save masks
	a2 = inb(PIC2_DATA);
 
	outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);  // starts the initialization sequence (in cascade mode)
	io_wait();
	outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
	io_wait();
	outb(PIC1_DATA, offset1);                 // ICW2: Master PIC vector offset
	io_wait();
	outb(PIC2_DATA, offset2);                 // ICW2: Slave PIC vector offset
	io_wait();
	outb(PIC1_DATA, 4);                       // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
	io_wait();
	outb(PIC2_DATA, 2);                       // ICW3: tell Slave PIC its cascade identity (0000 0010)
	io_wait();
 
	outb(PIC1_DATA, ICW4_8086);
	io_wait();
	outb(PIC2_DATA, ICW4_8086);
	io_wait();
 
	outb(PIC1_DATA, a1);   // restore saved masks.
	outb(PIC2_DATA, a2);
}
 

Wywołanie tej funkcji jest następujące:

 
void init_pic(){

	PIC_remap(0x00,0x20);
	PIC_remap(0x01,0x21);
	PIC_remap(0x02,0x22);
	PIC_remap(0x03,0x23);
	PIC_remap(0x04,0x24);
	PIC_remap(0x05,0x25);
	PIC_remap(0x06,0x26);
	PIC_remap(0x07,0x27);
	PIC_remap(0x08,0x28);
	PIC_remap(0x09,0x29);
	PIC_remap(0x0A,0x2A);
	PIC_remap(0x0B,0x2B);
	PIC_remap(0x0C,0x2C);
	PIC_remap(0x0D,0x2D);
	PIC_remap(0x0E,0x2E);
	PIC_remap(0x0F,0x2F);
}

Następnie w kernelu wykonuję inicjację IRQ :

 
	init_irq(0x20, 0x28);

Funkcja ma postać:

 
void init_irq(int pic1, int pic2)
{
   // send ICW1 
   outb(PIC1, ICW1);
   outb(PIC2, ICW1);

   // send ICW2 
   outb(PIC1 + 1, pic1); // remap 
   outb(PIC2 + 1, pic2); //  pics 

   // send ICW3 
   outb(PIC1 + 1, 4); // IRQ2 -> connection to slave 
   outb(PIC2 + 1, 2);

  //  send ICW4 
   outb(PIC1 + 1, ICW4);
   outb(PIC2 + 1, ICW4);

   // enable all IRQs 
    outb(0x21, 0);
    outb(0xA1, 0); 
}

Rozumiem, że po wykonaniu tej funkcji wszystkie przerwania są aktywne. Po włączeniu przerwań system wyrzuca ex.

Ale gdy w kernelu odblokuję tylko przerwanie od klawiatury:


	outb(0x21, 0xFD);     	
	outb(0xa1, 0xff);
	sti();	 

To przerwanie działa jak należy. Pobieranie znaków też działa i mogę wielokrotnie obsłużyć to przerwanie.

Moje pytanie jest następujące co robię źle, że nie działa mi reszta przerwań? Moim zdaniem źle wykonuję przekierowanie adresu przerwań z niższych na wyższe gdyż po zakomentowaniu funkcji init_pic() przerwanie od klawiatury nadal działa, ale inne standardowo wyrzucają ex.

1

Przypuszczam że tak będzie sprawniej przemapować:

	; zachowaj oryginalne rejestry
	push	rax

	mov	al,	0x11	; przełącz obydwa układy w tryb inicjalizacji
	out	0x20,	al
	out	0xa0,	al

	mov	al,	0x20	; przeindeksuj pic master na przerwania od 0x20 do 0x27
	out	0x21,	al

	mov	al,	0x28	; przeindeksuj pic slave na przerwania od 0x28 do 0x30
	out	0xa1,	al

	mov	al,	4	; pic0 ustaw jako główny (master)
	out	0x21,	al

	mov	al,	2	; pic1 ustaw jako pomocniczy (slave)
	out	0xa1,	al

	mov	al,	1	; obydwa kontrolery w tryb 8086
	out	0x21,	al
	out	0xa1,	al

	; wyłącz nieobsługiwane przerwania sprzętowe
	mov	al,	11111100b	; irq7, irq6, irq5, irq4, irq3, irq2
	out	0x21,	al	; pic0 master

	mov	al,	11111111b	; irq15, irq14, irq13, irq12, irq11, irq10, irq9, irq8
	out	0xa1,	al	; pic1 slave

	; przywróć oryginalne rejestry
	pop	rax
0

akasei bardzo dziękuję za odpowiedź.

Po dokładnym sprawdzeniu mojego kodu oraz porównania z powyższym przykładem znalazłem, że robiłem prze-mapowanie PIC popranie następującą funkcja:

void init_irq(int pic1, int pic2)
{
   // send ICW1 
   outb(PIC1, ICW1);
   outb(PIC2, ICW1);

   // send ICW2 
   outb(PIC1 + 1, pic1); // remap 
   outb(PIC2 + 1, pic2); //  pics 

   // send ICW3 
   outb(PIC1 + 1, 4); // IRQ2 -> connection to slave 
   outb(PIC2 + 1, 2);

  //  send ICW4 
   outb(PIC1 + 1, ICW4);
   outb(PIC2 + 1, ICW4);

   // enable all IRQs 
    outb(0x21, 0xFC);     // wlaczenie przerwania klawiatury oraz timera
    outb(0xA1, 0xFF); 
}
 

Wywołanie funkcji:

 
	init_irq(0x20, 0x28);

Niestety nadal nie działa przerwanie od timera. Jako, że nie lubię się poddawać będę walczył do końca ;) (w końcu zadziała).

Sytuacja jest następująca, po wywołaniu przerwania IRQ0 dostaję napis "System halted" czyli wyłapanie wyjątku. Prawdopodobnie jest to wyjątek nr 7. Po przejściu do systemu robię następujące operacje:

Ładowanie GDT:

gdt.h :

static gdt_descr_t gdt[GDT_LEN];
static gdt_ptr_t gdt_ptr;

void gdt_init();
void setup_seg(uint8 index, uint32 base, uint32 limit, uint8 type);


gdt.c:

static void gdt_set_desc(gdt_descr_t* descr, u32int base, u32int limit, u8int access, u8int granularity)
{
        descr->base_low = (base & 0xFFFF);
        descr->base_middle = (base >> 16) & 0xFF;
        descr->base_high = (base >> 24) & 0xFF;
        descr->limit_low = (limit & 0xFFFF);
        descr->granularity = ((limit >> 16) & 0x0F) | (granularity & 0xF0);
        descr->access = access;
}

void gdt_init()
{
        gdt_set_desc(&gdt[0], 0, 0, 0, 0);                // null
        gdt_set_desc(&gdt[1], 0, 0xFFFFFFFF, 0x9A, 0xCF); // ring0 code
        gdt_set_desc(&gdt[2], 0, 0xFFFFFFFF, 0x92, 0xCF); // ring0 data
        gdt_set_desc(&gdt[3], 0, 0xFFFFFFFF, 0xFA, 0xCF); // ring3 code
        gdt_set_desc(&gdt[4], 0, 0xFFFFFFFF, 0xF2, 0xCF); // ring3 data
 
        gdt_ptr.base = (u32int) &gdt;
        gdt_ptr.limit = sizeof(gdt_descr_t) * GDT_LEN - 1;
 
        gdt_set(&gdt_ptr);
}



Struktury:

typedef struct gdt_descr
{
	u16int limit_low;
	u16int base_low;
	u8int base_middle;
	u8int access;
	u8int granularity;
	u8int base_high;
} __attribute__((packed)) gdt_descr_t;

typedef struct gdt_ptr
{
	u16int limit;
	u32int base;
} __attribute__((packed)) gdt_ptr_t;

 

Funkcja gdt_set():

[GLOBAL gdt_set]
 
gdt_set:
        mov     eax, [esp+4]    ; get passed pointer
        lgdt    [eax]           ; load new GDT pointer
 
        mov     ax, 0x10        ; load all data segment registers
        mov     ds, ax
        mov     es, ax
        mov     fs, ax
        mov     gs, ax
        mov     ss, ax
        jmp     0x08:.flush     ; far jump to code segment
.flush:
        ret

Po przejściu do funkcji k_main() wywołuję gdt_init();
Następnie ładuję IDT w następujący sposób:

 
idt.h:


#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01

#define TRAP_GATE      0x8F00
#define IRQ_GATE       0x8E00


void unknown_interrupt_isr();	


void int80_isr();
void int80();

// Obsluga przerwania klawiatury
void isrKlaw();
void do_isrKlaw();

// Obsluga przerwania timer
void do_isrTimer();
void isrTimer();

// Obsluga wyjatkow
void exception_isr0();
void exception_isr1();
void exception_isr2();
void exception_isr3();
void exception_isr4();
void exception_isr5();
void exception_isr6();
void exception_isr7();
void exception_isr8();
void exception_isr9();
void exception_isr10();
void exception_isr11();
void exception_isr12();
void exception_isr13();
void exception_isr14();
void exception_isr15();
void exception_isr16();

// Inicjacja irq
void init_irq(int pic1, int pic2);
void setup_int(int i, unsigned long p_hand, unsigned short type);


idt.c:

void init_irq(int pic1, int pic2)
{
   // send ICW1 
   outb(PIC1, ICW1);
   outb(PIC2, ICW1);

   // send ICW2 
   outb(PIC1 + 1, pic1); // remap 
   outb(PIC2 + 1, pic2); //  pics 

   // send ICW3 
   outb(PIC1 + 1, 4); // IRQ2 -> connection to slave 
   outb(PIC2 + 1, 2);

  //  send ICW4 
   outb(PIC1 + 1, ICW4);
   outb(PIC2 + 1, ICW4);

   // enable all IRQs 
    outb(0x21, 0xFD);
    outb(0xA1, 0xFF); 
}


// Funkcja edytujaca wpisy w IDT

void setup_int(int i, unsigned long p_hand, unsigned short type)
{
   gate_desc *idt = (gate_desc *)KERNEL_IDT;
   idt[i].offset_0 = p_hand;
   idt[i].selector = 0x08;
   idt[i].type = type;
   idt[i].offset_16 = (p_hand >> 16);
}

void init_idt()
{
   int i;

   for(i = 17; i < 256; i++)
   {
       	 setup_int(i, (unsigned long)(void*)&unknown_interrupt_isr, IRQ_GATE);
   }

   setup_int(0, (unsigned long)(void*)&exception_isr0, TRAP_GATE);
   setup_int(1, (unsigned long)(void*)&exception_isr1, TRAP_GATE);
   setup_int(2, (unsigned long)(void*)&exception_isr2, TRAP_GATE);
   setup_int(3, (unsigned long)(void*)&exception_isr3, TRAP_GATE);
   setup_int(4, (unsigned long)(void*)&exception_isr4, TRAP_GATE);
   setup_int(5, (unsigned long)(void*)&exception_isr5, TRAP_GATE);
   setup_int(6, (unsigned long)(void*)&exception_isr6, TRAP_GATE);
   setup_int(7, (unsigned long)(void*)&exception_isr7, TRAP_GATE);
   setup_int(8, (unsigned long)(void*)&exception_isr8, TRAP_GATE);
   setup_int(9, (unsigned long)(void*)&exception_isr9, TRAP_GATE);
   setup_int(10, (unsigned long)(void*)&exception_isr10, TRAP_GATE);
   setup_int(11, (unsigned long)(void*)&exception_isr11, TRAP_GATE);
   setup_int(12, (unsigned long)(void*)&exception_isr12, TRAP_GATE);
   setup_int(13, (unsigned long)(void*)&exception_isr13, TRAP_GATE);
   setup_int(14, (unsigned long)(void*)&exception_isr14, TRAP_GATE);
   setup_int(15, (unsigned long)(void*)&exception_isr15, TRAP_GATE);
   setup_int(16, (unsigned long)(void*)&exception_isr16, TRAP_GATE);

   setup_int(32, (unsigned long)(void*)&isrTimer, IRQ_GATE);
   setup_int(33, (unsigned long)(void*)&isrKlaw, IRQ_GATE);

   setup_int(0x80, (unsigned long)(void*)&int80_isr, IRQ_GATE);

   load_idt();
}

Funkcja load_idt() w asemblerze:

[SECTION .text]

[GLOBAL load_idt]
load_idt:
  lidt [idt_descr]
  ret

idt_descr:
  .size: dw 2048
  .addr: dd 0x3000

Obsługa przerwań w asemblerze:

[BITS 32]

[SECTION .text]

[GLOBAL isrKlaw] 
isrKlaw: 
     pusha
     push gs 
     push fs 
     push es 
     push ds 

EXTERN do_isrKlaw 
     call do_isrKlaw 

     pop ds 
     pop es 
     pop fs
     pop gs 
     popa
     IRET

[GLOBAL isrTimer] 
isrTimer: 

     pusha
     push gs 
     push fs 
     push es 
     push ds 

EXTERN do_isrTimer
     call do_isrTimer

     pop ds 
     pop es 
     pop fs 
     pop gs 
     popa
     IRET



[GLOBAL int80_isr]
int80_isr:
  pusha
  push gs
  push fs
  push es
  push ds

EXTERN int80
  call int80

  pop ds
  pop es
  pop fs
  pop gs
  popa
  iret

extern exception_handler 
 
%macro EXCEPTION_ISR 1
[GLOBAL exception_isr%1]
exception_isr%1:
	pusha
	push gs
	push fs
	push es
	push ds

	push %1
	
	call exception_handler
	
	pop ds
	pop es
	pop fs
	pop gs
	popa
	iret
%endmacro

EXCEPTION_ISR 0
EXCEPTION_ISR 1
EXCEPTION_ISR 2
EXCEPTION_ISR 3
EXCEPTION_ISR 4
EXCEPTION_ISR 5
EXCEPTION_ISR 6
EXCEPTION_ISR 7
EXCEPTION_ISR 8
EXCEPTION_ISR 9
EXCEPTION_ISR 10
EXCEPTION_ISR 11
EXCEPTION_ISR 12
EXCEPTION_ISR 13
EXCEPTION_ISR 14
EXCEPTION_ISR 15
EXCEPTION_ISR 16


[GLOBAL unknown_interrupt_isr]
unknown_interrupt_isr:
  iret

Funkcje obsługi w c:


void exception_handler( char nr, char nr1, char nr2 )
{
   print("System halted.");
  // printInt(nr);
  // printInt(nr1);
  // printInt(nr2);

   __asm__ __volatile__ ("cli\n"
                         "hlt");
}

void do_isrTimer(){

	print("To jest przerwanie Timera");
	outb(0x20,0x20);
}

// Funkcja obslugi przerwania klawiatury
void do_isrKlaw(){

//	print("To jest przerwanie do klawiatury");

	key = inb(0x60);		
	key = scancode_to_ascii(key);

        if(key > 0 && key < 190){
	      setBuforChar(key);
        }
	outb(0x20,0x20);		// zakonczenie przerwania
}

// Funkcja obslugi przerwania int80

void int80()
{
   print("To jest int 80");
   outb(0x20, 0x20);
}

 

Następnie wywołuję init_irq(0x20, 0x28) oraz włączam przerwania. Po skompilowaniu oraz uruchomieniu systemu dostaję informację "System halted". Niestety już nie wiem gdzie szukać błędu. Wydaje się być wszystko ok (na mój obecny stan wiedzy).
Jeszcze jest bardzo ciekawa sytuacja. Mianowicie jeśli w funkcji: do_isrTimer() jest od-komentowana ostatnia linia "outb(0x20,0x20)" to nie działają przerwania klawiatury (oczywiście jeśli włączone są tylko przerwania klawiatury bo jeśli klawiatura + timer = error). Gdy za komentuję w/w linię przerwania klawiatury działają. Jakim cudem jeśli to jest zupełnie inna "funkcja" ??
W załączniku dołączam zrzut ekranu po zatrzymaniu tak prostego kernela.

0
czornexxx napisał(a):

Sytuacja jest następująca, po wywołaniu przerwania IRQ0 dostaję napis "System halted" czyli wyłapanie wyjątku. Prawdopodobnie jest to wyjątek nr 7.

Podaj mi działający obraz Twojego systemu. Podmontuje u siebie i zobacze jak wygląda błąd i z czego się wziął (mam taką nadzieje, jeśli disasm będzie czytelny).

Popracuje nad nim około 17 lub 23.

Widze, że obraz podesłany przez Ciebie działa mi prawidłowo. Działają też procesy 'demo' i 'help'.

user image

0

Witam.
Panowie z przerwaniami sobie poradziłem. Wystarczyło zmienić flagę przy kompilacji pliku który obsługuje przerwania z -f coff na -f elf.
Ech taki prosty błąd, a kosztował masę czasu.

Teraz kolejny problem :(.
System uruchamia się pod: QEMU, VBoxem, ale na fizycznym PC zatrzymuje się na bootloaderze (napis A20 Enable) i niestety nie przejdzie dalej. Pod VMware sytuacja jest taka sama jak na fizycznym kompie.
Co może być przyczyną? Kernela ładuję tak jak na w/w plikach. Nic innego nie zmieniałem.

Z góry dziękuję za pomoc.
Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1