Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - nnosdev

Seiten: 1 [2] 3 4
21
Du brauchst dazu GDB.

Ein paar Anleitungen:

http://www.lowlevel.eu/wiki/Debugging#bochs_.2F_QEMU
http://wiki.osdev.org/How_Do_I_Use_A_Debugger_With_My_OS#Use_gdb_with_Qemu

Im Prinzip musst du nur qemu mit -s -S starten, gdb mit dem Kernel als Parameter starten und dann target remote :1234 eingeben.

Okay, ich hab das zum Laufen gebracht. Werd mir das jetzt mal anschaun :)
22
Du sprichst von Debugging :D

Also mein Setup sieht im Moment noch so aus:

Ich verwende Eclipse zum coden und benütze ein Makefile um den Kernel zu starten.
Leider hab ich nicht den Hauch einer Ahnung wie ich am einfachsten Debuggen kann bzw wie ich das entsprechend einrichten kann.

Kannst du mir da was empfehlen?

23
Also GP höre ich zum ersten Mal :D
Mein Kernel macht in diesem Falle also noch nichts ^^

Aber es ist mir ja schon ein Rätsel wieso der PC auf
0x001016f9
landet obwohl davor eindeutig
0x0010193c:  jmp    0x1018d5
steht..
----------------
IN:
0x0010193a:  push   $0xd
0x0010193c:  jmp    0x1018d5

----------------
IN: Isr_Handler
0x001016f9:  movl   $0x10342c,(%esp)
0x00101700:  call   0x1000d2


Also ich hab hier jetzt schon ewig versucht dem Grund auf die Schliche zu kommen. Leider hab ich bemerkt, dass das nicht nur manchmal auftritt sondern fast immer. Das Problem fängt eigentlich immer bei einem Interrupt an.

Die main sieht im Moment so aus:
Gdt_Init();
Idt_Init();

Thread init_threads[2];
cpu_state *init_states[2];
init_states[0] = Thread_Init(&init_threads[0], (uint32_t*)&task_a, stack_a);
init_states[1] = Thread_Init(&init_threads[1], (uint32_t*)&task_b, stack_b);

Scheduler_Init(scheduler, init_states, 2);

dprint("lets go ..");
while(1);

Davor und danach passieren keine wesentlichen Dinge. Das Problem wird tatsächlich von einem Interrupt verursacht.
Sobald die IDT installiert ist und die Interrupts enabled werden kommt natürlich sofort INT 20 vom PIC..
Danach geht er wie geplant in die Interrupt-Routine aber scheitert da irgendwo nach iret

----------------
IN:
0x001018f0:  iret   

----------------
IN:
0x00101944:  cli   

----------------
IN:
0x00101945:  push   $0xd
0x00101947:  jmp    0x1018d5

----------------
IN: Isr_Handler
0x001016f9:  movl   $0x10342c,(%esp)
0x00101700:  call   0x1000d2

qemu: fatal: Trying to execute code outside RAM or ROM at 0xd08ec08e

EAX=000000fe EBX=666f5365 ECX=2e532074 EDX=0000b800
ESI=00000000 EDI=00000000 EBP=d88e0000 ESP=fffffeec
EIP=d08ec08e EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 00000000 00000000
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]

Hier die allgemeine Interrupt Service Routine:
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax (inverted order)
push eax

push esp ; pointer to cpu_state struct
call Isr_Handler
mov esp, eax

pop eax
popa

add esp, 8
sti
iret

Obigen stub hab ich von einem anderen Tutorial. Es müsste aber quasi dasselbe machen wie der vom lowlevel Tutorial. 

Nur ne kleine Frage am Rande: Kann ich mir das qemu log auch in intel-Syntax ausgeben lassen? ^^
1016f9: c7 04 24 2c 34 10 00 mov    DWORD PTR [esp],0x10342c
ist Intel-Syntax.
Ja, das ist auf dem dump-file. Die verwendet die intel-Syntax aber das qemu.log leider nicht.
24
Hi taljeth :)

Also ich hab das mal versucht. Muss gestehen, dass ich noch immer nicht ganz nachvollziehen kann was da passiert (vor allem versteh ich nicht warum das nur manchmal passiert und manchmal eben nicht).

Kannst du mir vielleicht vorweg erklären wo die Register EBP und EIP ihre Werte bekommen?
EBP ist der Basepointer vom Stack und EIP hat das Offset zur nächsten Instruktion soweit ich das richtig verstanden habe.

Beim Suchen sind eigentlich nur mehr Fragen entstanden ^^
Ich hab mir den Output geben lassen wenn das System läuft und problemlos zwischen Task A und B wechselt. Als erstes fiel mir auf, dass anscheinend immer ein INT 32 ausgelöst wird. Woher kommt der? Ich muss gestehen, dass mir das hier: http://www.ctyme.com/intr/int-32.htm nicht wirklich weiter hilft :D

Also bei meinem Problem hier seh ich im qemu.log (mit dem parameter -d in_asm) folgendes..

Ich kann sehen, dass Idt_InstallEntried() noch die Interrupt-Table erstellt. Ich gehe davon aus das IN: Func_Name() dafür steht, aus welcher Funktion die Instruktionen kommen. Liege ich da richtig?
Danach kommt noch der Befehl sti für das enablen der Ints.

Jetzt wirds spannend.. Es kommt ein INT 20, der Isr_Handler() wird gerufen, dieser ruft Scheduler_Schedule(), der kommt zurück in Isr_Handler().. wo anscheinend nocht outb(0x20, 0x20) end of interrupt ausgeführt wird. Danach springt der Code zurück in isr_common_stub (also der Interrupt-Main sozusagen).

Hier kann ich noch sehen, dass alles bis zum iret läuft. Da wirds etwas komisch.. Plötzlich befindet sich die CPU hier:

00101a29 <isr13>:
  101a29: fa                    cli   
  101a2a: 6a 0d                push   0xd
  101a2c: eb 97                jmp    1019c5 <isr_common_stub>

Laut qemu.log werden
----------------
IN:
0x00101a2a:  push   $0xd
0x00101a2c:  jmp    0x1019c5

ausgeführt. Sollte sich der PC da nicht wenn schon in der isr20 befinden das es ja ein INT20 ist?
Unmittelbar danach befindet sich der PC hier:

(IN: Isr_Handler)
dprint("[ISR] Exception captured. Kernel stopped.");
  1016f9: c7 04 24 2c 34 10 00 mov    DWORD PTR [esp],0x10342c
  101700: e8 cd e9 ff ff        call   1000d2 <dprint>

OBWOHL der vorige Befehl jmp    0x1019c5 war ..

Das ist dann die Stelle wo dann eben die Meldung von qemu kommt
qemu: fatal: Trying to execute code outside RAM or ROM at 0xd08ec08e
Ich weiß, das ist schon recht viel verlangt hier um Hilfe zu bitten aber ich kann nicht wirklich nachvollziehen wie das passiert.

Nur ne kleine Frage am Rande: Kann ich mir das qemu log auch in intel-Syntax ausgeben lassen? ^^

25
Ein besserer Betreff ist mir nicht eingefallen ^^

Habe das Multitasking implementiert. Das eigenartige.. mal funktioniert es und mal nicht..
Also manchmal startet alles normal und der Output ist wie erwartet (A bzw. B)

Aber manches mal bekomme ich im Terminal folgendes zu lesen:

qemu: fatal: Trying to execute code outside RAM or ROM at 0xd08ec08e

EAX=000000fe EBX=666f5365 ECX=2e532074 EDX=0000b800
ESI=00000000 EDI=00000000 EBP=d88e0000 ESP=fffffeec
EIP=d08ec08e EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00108820 00000027
IDT=     00104000 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000008 CCD=fffffedc CCO=SUBL   
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000

ich hab keine Ahnung wie/wo er auf 0xd08ec08e kommt. Hat jemand eine Idee wie ich an das Problem herangehen kann?
26
Das Wiki / Re: Dead-Links
« am: 04. April 2012, 19:34 »
Gerne
27
OS-Design / Re: Global Descriptor Table (GDT)
« am: 04. April 2012, 11:36 »
Ja, das hilft schon sehr!
Danke :)
28
Lowlevel-Coding / Re: Tastaturtreiber
« am: 03. April 2012, 21:53 »
Danke :D

29
Lowlevel-Coding / Re: Tastaturtreiber
« am: 03. April 2012, 21:16 »
Hi,

das hier ist keine Antwort sondern eine Frage.

Und zwar.. ich hab meine Interrupt Service Routinen geschrieben und soweit funktioniert das auch.
Wenn ich jetzt eine Taste drücke, dann empfange ich diesen Interrupt nur ein einziges Mal.
Jeder weitere Tastendruck wird dann nicht mehr verarbeitet (IRQ 0 wird jedoch permanent weiter
bearbeitet).

void isr_handler(cpu_state_t status)
{
if(status.int_no <= 0x1F) {
dprint("[ISR] Exception captured. Kernel stopped.");

while(1) {
// Stop CPU
asm volatile ("cli; hlt");
}
}else if (status.int_no >= 0x20 && status.int_no <= 0x2f) {

dprint("[ISR] Hardware interrupt received");

    if (status.int_no >= 0x28) {
        outb(0xA0, 0x20);
    }

    outb(0x20, 0x20); // EOI
}

dprint("[ISR] Received (but unhandled) interrupt: 0x%X", status.int_no);
}

Hat jemand eine Ahnung woran das liegen könnte?
30
Das Wiki / Dead-Links
« am: 03. April 2012, 20:11 »
http://www.lowlevel.eu/wiki/Linkliste#Offizielle_Spezifikationen

Habe nicht alle überprüft, aber
Protected Mode
    deutsch PM-Grundlagen - TeeJay
    deutsch Kernel in C - TeeJay
    deutsch Kernel in C++ - TeeJay
scheinen nicht mehr zu funktionieren.
31
OS-Design / Re: Global Descriptor Table (GDT)
« am: 29. March 2012, 23:38 »
Ah, das macht natürlich Sinn! Hätte ich mir eigentlich denken können..

Also ich versuch die qemu.log stärker in meinen Alltag einzubauen, aber es ist
etwas mühsam wenn man nicht weiß was die Einträge bedeuten.

Kennt da jemand einen brauchbaren Link?

Keine Ahnung wie ich mit diesen Informationen umgehen soll.
0: v=03 e=0000 i=1 cpl=0 IP=0008:00100bab pc=00100bab SP=0010:00104000 EAX=00104840
32
Lowlevel-Coding / Re: memset();
« am: 25. March 2012, 14:05 »
Okay, dann werd ich sie so implementieren :)


:D

Die Frage hab ich mir schon oft gestellt. Wie bei dir wärs bei mir eher der Gruppenzwang als das Wissen darum, weshalb man das so nennt ^^
33
Lowlevel-Coding / Re: memset();
« am: 24. March 2012, 23:38 »
Hallo XanClic,

danke für die Antwort!

Also nach meinem Post hab ich mir eben gedacht, dass es wohl sinnvoller wäre,
jedes Byte einzeln zu setzen. Im Grunde sieht meine Funktion jetzt aus
wie die von dir gepostete.
Würdest du mir diese Implementierung empfehlen oder lieber eine andere?


Prinzipiell spricht aber nichts dagegen, den ganz naiven Ansatz zu gehen:
void *memset(void *ptr, uint32 value, size_t bytes)
{
    uint8 *pt = ptr;
    while (bytes--)
        *(pt++) = value;
    return ptr;
}

In der Annahme, dass du ein einigermaßen standardkonformes memset schreiben willst, das eben byteweise arbeitet und in der weiteren Annahme, dass deine uintXX-Typen den normalen uintXX_t-Typen entsprechen.

Ad uintXX_t-Typen: Wofür steht eigentlich der Zusatz "_t"

34
OS-Design / Re: Global Descriptor Table (GDT)
« am: 24. March 2012, 23:19 »
Ich hätte da doch noch eine Frage zum objdump..

Wie kann ich mir die folgenden Adressen und deren Einträge
ausgeben lassen? Keine Ahnung warum, aber genau diese hier
sind "auspunktiert".

Disassembly of section .bss:

00102000 <gdt>:
...
00102028 <gdt_ptr>:
...
00104030 <kernel_stack>:
...
00104040 <idt>:
...
00104840 <idt_ptr>:
...
00104860 <gdt>:
...
00104888 <gdt_ptr>:
...
001048a0 <idt>:
...
001050a0 <idt_ptr>:
...
35
Lowlevel-Coding / memset();
« am: 24. March 2012, 23:05 »
Da ich mir nicht ganz sicher bin, ob man dieser Funktion vertrauen kann wollte ich
hier mal nachfragen.. Simuliert wird auf einem 32-Bit i386er.

void* memset(void *ptr, uint32 value, size_t bytes)
{
if(bytes < 1)
return 0;

uint32 *pt = (uint32*) ptr;

// Last two bytes are going to be lost after the bit shift
uint32 carry = bytes & 0x3;

// Integer division by 4
bytes >>= 2;

while(bytes) {
*pt = value;
pt++;
bytes--;
}

if(carry) {
pt++;
*pt = value;
}

return ptr;
}

Kann man dieser Funktion vertrauen? ^^
36
OS-Design / Re: Global Descriptor Table (GDT)
« am: 24. March 2012, 11:07 »
+hehe+

Ja es funktioniert jetz :)
Es lag tatsächlich an der Platzierung der Funktion. Entweder ich habs strukturiert indem ich "section .my_section" angegeben
oder die Funktion ausgelagert habe in eine gdt.S Datei
Danke für die Hilfe.

37
Das Wiki / Syntax-Highlighting
« am: 23. March 2012, 21:06 »
Ich weiß, da steht Wiki, aber irgendwie wärs super, wenn das Forum auch
Syntax-Highlighting unterstützen würde für C/C++ bzw. Assembler, ..
38
OS-Design / Re: Global Descriptor Table (GDT)
« am: 23. March 2012, 19:07 »
Okay,

ich hab im Grunde alles richtig gemacht.
Hab folgendes geändert:

Habe die Gdt_Flush()-Methode in ein eigenes File gelegt.
global _start
_start:

; ......

section .bss
resb 8192 ; 8kB stack
kernel_stack:

; Method for flushing the Global Descriptor Table
global Gdt_Flush
Gdt_Flush:
mov eax, [esp+4] ; Get the pointer to the GDT, passed as parameter
lgdt [eax] ; Load new GDT Pointer

mov ax, 0x10 ; 0x10 is the offset in the GDT to out data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:.flush ; 0x08 is the offset to our code segment: Far jump
.flush:
ret
39
OS-Design / Re: Global Descriptor Table (GDT)
« am: 23. March 2012, 18:25 »
Danke für den Tipp!

Also ich hab in der qemu.log folgendes gefunden.

0: v=06 e=0000 i=0 cpl=0 IP=0008:00104094 pc=00104094 SP=0010:00103f8c EAX=00002029

Hat das einen Grund weshalb ich den  Eintrag mit "0: v= .." suchen soll?

Danach habe ich in der Dump-File die Adresse gesucht.
Aufgerufen hab ich objdump mit objdump --disassemble-all nnOS -M intel > nnOSdump


00104088 <gdt_ptr>:
...

An der Stelle an die der PC zeigt scheint sich mein GDT-Pointer zu befinden.
Interpretiere ich das richtig? Leider hilft mir das jetzt nicht viel.
Kann mir nur vorstellen, dass im PC nicht die Adresse der Base stehen sollte.

struct gdt_ptr_struct {
uint16 limit;
uint32 base;
} __attribute__ ((packed));

*EDIT:

Hab diesen Eintrag noch entdeckt in der Log

GDT=     000cb9ec 00000027

Also wenn 00000027 die Größe der Tabelle sein soll, dann ist das
ja schon mal nicht so schlecht.
Aber keine Ahnung wofür 000cb9ec steht.
Wenn das die Adresse der GDT sein soll, dann wirds wohl daran scheitern.
40
OS-Design / Re: Global Descriptor Table (GDT)
« am: 23. March 2012, 16:53 »
Hi Svenska,

ja ich hab darauf geachtet.
struct gdt_entry_struct {
uint16 limit_low;
uint16 base_low;
uint8 base_middle;
uint8 access;
uint8 granularity;
uint8 base_high;
}__attribute__ ((packed));
typedef struct gdt_entry_struct gdt_entry;


Aber mir kommt so vor, als ob das nicht ganz so mit der Tabelle übereinstimmt.
http://www.lowlevel.eu/wiki/Global_Descriptor_Table

Byte
6 Flags 0-3
6 Limit 16-19
7 Base 24-31

Für diesen Eintrag scheint man 32 Bit zu benötiegen jedoch sind
nur 2 Byte laut Tabelle dafür vorgesehen. Das kommt mir ein wenig Spanisch
vor.. ^^
Seiten: 1 [2] 3 4

Einloggen