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.


Themen - nnosdev

Seiten: [1]
1
Lowlevel-Coding / ISR Common Stub -> INT13
« am: 24. January 2014, 11:42 »
Hallo Leute,

ich weiß nicht woran das hier liegt. Folgendes passiert bei mir:


%macro isr_stub 1
global isr%1
isr%1:
cli
push byte 0
push byte %1
jmp isr_common_stub
%endmacro

isr_common_stub:
; save cpu state by pushing
; main purpose registers onto the stack

pusha 

mov eax, ds
push eax

mov eax, 0x10
mov ds, eax
        mov es, eax
        mov fs, eax
mov gs, eax

push esp
call Isr_Handler ; call interrupt handler
mov esp, eax

pop eax
mov ds, eax ; get old ds
        ;mov es, eax
        ;mov fs, eax
;mov gs, eax

popa

add esp, 8 ; pop error code, interrupt number
sti ; enable interrupts
iret ; interrupt return

Nachdem das Programm vom Isr_Handler zurückkehrt löst es bei der Instruktion mov ds, eax einen INT13 aus. Kommentiere ich dies Instruktion aus läuft alles soweit ohne Probleme.

Der Plan ist VOR Isr_Handler den Kernel-Mode aufzusetzen indem zuvor das verwendete DS Register gepush wird und dnach die Register entpsrechend gesetzt werden. Nach Isr_Handler will ich das alte DS wieder auslesen und in das Register schreiben.

Ich komme nicht wirklich dahinter was das Problem ist..

cpu_state* Isr_Handler(cpu_state *state) {

if (state->int_no <= 0x1F) {
dprint("[ISR] Exception captured. Kernel stopped.");

dprint("CPU State:");
dprint("     INT: %d, RING: %d, ERRCODE: 0x%X\n"
"\n"
"     EAX: 0x%X EBP: 0x%X EBX: 0x%X ECX: 0x%X\n"
"     EDI: 0x%X EDX: 0x%X EIP: 0x%X ESI: 0x%X\n"
"     ESP: 0x%X EFLAGS: 0x%X\n"
"     CS:  0x%X DS:  0x%X SS:  0x%X", state->int_no,
state->useresp, state->err_code, state->eax, state->ebp, state->ebx,
state->ecx, state->edi, state->edx, state->eip, state->esi,
state->esp, state->eflags, state->cs, state->ds, state->ss);

while (1) {
// Stop CPU
asm volatile ("cli; hlt");
}
}
// Hardware-Interrupts
if (state->int_no >= 0x20 && state->int_no <= 0x2f) {

dprint("[ISR] Hardware interrupt 0x%X received.", state->int_no);
  dprint("     INT: %d, RING: %d, ERRCODE: 0x%X\n"
          "\n"
          "     EAX: 0x%X EBP: 0x%X EBX: 0x%X ECX: 0x%X\n"
          "     EDI: 0x%X EDX: 0x%X EIP: 0x%X ESI: 0x%X\n"
          "     ESP: 0x%X EFLAGS: 0x%X\n"
          "     CS:  0x%X DS:  0x%X SS:  0x%X\n",
          state->int_no, state->useresp, state->err_code,
          state->eax,    state->ebp,     state->ebx,      state->ecx,
          state->edi,    state->edx,     state->eip,      state->esi,
          state->esp,    state->eflags,
          state->cs,     state->ds,      state->ss);

  //uint32_t tss[32] = { 0x00, 0x00, 0x10 };

// Call Scheduler
if (state->int_no == 0x20) {
state = Scheduler_Schedule(scheduler, state);
}

if (state->int_no >= 0x28) {
// TODO Keyboard driver
outb(0xA0, 0x20);
}

outb(0x20, 0x20); // End of interrupt (EOI)
return state;
}

2
OS-Design / malloc(), free()
« am: 16. January 2013, 13:35 »
Hallo Leute!

Für eine Übung auf der Uni müssen wir u.A. einen Task erledigen, bei dem malloc() und free() für den Userspace zu implementieren sind. Ich bin im Moment noch der Meinung malloc() soweit in Ordnung implementiert zu haben und zwar wie folgt:

Über sbrk() stelle ich fest wie viel Speicher dem Programm zur Verfügung steht und verwalte von malloc() reservierten Speicher in einer doppelt verketten Liste über die ich feststellen kann, ob bei einem weiteren malloc() zwischen zwei Datenbereichen Platz ist oder ob neuer Speicher vom Kernel angefordert werden muss.

Soweit so gut..

Unser Kernel verwaltet seinen Speicher mit "Virtual Memory Areas". Das hab nicht ich implementiert, aber im Grunde gibt es einen VMA, der sozusagen unseren Heap repräsentiert und wächst, wenn man über malloc() Speicher anfordert. sbrk() vergrößert also ggf. diesen Bereich und die entsprechenden Pages werden gemappt.

Nun zum eigentlichen Problem:

Angenommen ein Userspace-Programm reserviert sich unmengen an Speicher.. Hausnummer: 1GB in diversen Arrays und am Schluss noch einen Pointer auf einen Integer am Ende der Daten. Wenn dieses Programm nun seinen gesamten Speicher bis auf diesen letzten einen Pointer freigibt, dann weiß zwar malloc(), dass am Heap Speicher frei wurde, aber der Kernel würde den VMA nicht verkleinern (können), da das Programm ja nach wie vor der Pointer auf den Integer am Ende der Daten gültig ist. Demnach würden die Pages gemappt bleiben und der RAM, obwohl schon ge-free()-d, "voll" bleiben.

Habe ich nun etwas falsch verstanden oder übersehe ich da etwas? Ich konnte nirgendwo eine Erklärung finden wann/wie/wo bei einem Aufruf von free() Speicher nicht nur am Heap freigegeben wird sondern eben auch tatsächlich Pages ungemappt werden um den physikalischen Speicher zu leeren.

Wäre dankbar für einen Schubs in die richtige Richtung!

LG Stefan :)
3
Lowlevel-Coding / Stack nach Interrupt..
« am: 07. October 2012, 11:08 »
Hallo Leute, bei mir funktioniert zwar soweit alles wunderbar, jedoch habe ich an einer bestimmten Stelle versucht genauer zu verstehen warum bis jetzt alles funktioniert und da kamen ein paar ungereimtheiten ans Licht.

Das hier ist mein struct für den CPU-Zustand:

typedef struct cpu_state_struct {
uint32_t ds;

uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t esp;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;

uint32_t int_no, err_code;
uint32_t eip, cs, eflags, useresp, ss; // um usersp und ss geht es...
} cpu_state;

Und hier der common_stub für die Interrupts:

isr_common_stub:
; pusha: (E)AX, (E)CX, (E)DX, (E)BX, (E)SP, (E)BP, (E)SI, (E)DI
; pushes these registers in that order on the stack
pusha

        mov eax, ds
push eax

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

pop eax
popa

add esp, 8
sti ; enable interrupts
iret ; interrupt return

Nun zu meiner Frage: Hier steht, auf Seite 346, steht:

The primary difference is that with the INT n
instruction, the EFLAGS register is pushed onto the stack before the return address. (The return
address is a far address consisting of the current values of the CS and EIP registers.) Returns
from interrupt procedures are handled with the IRET instruction, which pops the EFLAGS
information and return address from the stack.



In diesem Tutorial steht:

u32int eip, cs, eflags, useresp, ss; // Pushed by the processor automatically.

allerdings konnte ich dafür noch keinen Nachweis finden. CS:EIP bzw. EFLAGS ist klar, steht auch so in der Dokumentation aber mir fehlen noch die restlichen 8 Byte in dieser Rechnung. Also wann bzw. wo werden diese "automatisch" vom Prozessor gepusht? Was habe ich übersehen?

LG
4
Lowlevel-Coding / Assembler: mov eax, [esp+8]
« am: 28. July 2012, 19:17 »
Hallo Leute!

Ich hab einfach nichts gefunden.. warum darf man das so nicht machen (nach einem call):

_manipulate:
    mov eax, [esp+8]    ; First parameter
    mov ebx, [esp+12]   ; Second parameter
   
    mov byte [eax+11], bl
   
    ret

sondern muss zuerst ebp auf den Stack legen um dann mit ebp auf die Parameter zugreifen
zu können:

_manipulate:
    push ebp
    mov ebp, esp
   
    mov eax, [ebp+8]    ; First parameter
    mov ebx, [ebp+12]   ; Second parameter
   
    mov byte [eax+11], bl
   
    pop ebp
    ret

Ich kann ja esp auch anders manipulieren wie zb sub esp, 4 oder ähnliches.. Warum
bekomme ich bei einer indirekten Adressierung einen Segfault?
5
Hallo Leute!

Also ich hab parallel zum Tutorial von lowlevel.eu auch noch ein anderes (jamesmolloy.co.uk) offen.
Dabei fällt sofort auf, dass die Reihenfolge nicht dieselbe ist. Außerdem wird bei jamesmolloy.co.uk auch ein VFS
behandelt. Jetzt wollte ich fragen:

Macht es einen Unterschied in welcher Reihenfolge ich die essentiellen Elemente des Systems implementiere oder
gibt es Wege wie man es besser bzw. schlechter machen kann? Was wäre eurer Meinung nach die vernünftigste
Reihenfolge?
6
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?
7
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.
8
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? ^^
9
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, ..
10
OS-Design / Global Descriptor Table (GDT)
« am: 23. March 2012, 15:16 »
Hallo Leute!

Ich hab da ein Problem mit der GDT.

static void Gdt_SetEntry(uint32 index, uint32 base, uint32 limit, uint8 access,
uint8 gran) {
gdt.entry[index].base_low = (base & 0xFFFF);
gdt.entry[index].base_middle = (base >> 16) & 0xFF;
gdt.entry[index].base_high = (base >> 24) & 0xFF;

gdt.entry[index].limit_low = (limit & 0xFFFF);
gdt.entry[index].granularity = (limit >> 16) & 0x0F;

gdt.entry[index].granularity |= gran & 0xF0;
gdt.entry[index].access = access;
}

static void Gdt_InstallEntries() {
gdt_ptr.limit = (sizeof(gdt_entry) * GDT_ENTRIES) - 1;
gdt_ptr.base = (int) &gdt.entry[0];

Gdt_SetEntry(0, 0, 0, 0, 0);
Gdt_SetEntry(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
Gdt_SetEntry(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
Gdt_SetEntry(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
Gdt_SetEntry(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);

dprint("[GDT] sizeof gdt_entry %d Bytes", sizeof(gdt_entry));
dprint("[GDT] gdt_ptr.base 0x%X", gdt_ptr.base);
dprint("[GDT] gdt_ptr.limit 0x%X (GDT size %d Bytes)", gdt_ptr.limit, gdt_ptr.limit + 1);
dprint("[GDT] entry 1 0x%X", &gdt.entry[0]);
dprint("[GDT] entry 2 0x%X", &gdt.entry[1]);
dprint("[GDT] entry 3 0x%X", &gdt.entry[2]);
dprint("[GDT] entry 4 0x%X", &gdt.entry[3]);
dprint("[GDT] entry 5 0x%X", &gdt.entry[4]);

Gdt_Flush((uint32) &gdt_ptr);

dprint("[GDT] Returning from Gdt_Flush()");
}

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


Output:
[GDT] Initializing GDT
[GDT] sizeof gdt_entry 8 Bytes
[GDT] gdt_ptr.base 0x102000
[GDT] gdt_ptr.limit 0x27 (GDT size 40 Bytes)
[GDT] entry 1 0x102000
[GDT] entry 2 0x102008
[GDT] entry 3 0x102010
[GDT] entry 4 0x102018
[GDT] entry 5 0x102020

Leider fehlt die letzte Zeile [GDT] Returning from Gdt_Flush(). Da dürfte
wohl etwas nicht funktioniert haben.

Da ich den Fehler nicht finden kann, wollte ich fragen ob jemand weiß was
ich falsch gemacht habe.

LG; nnosdev
11
Lyrisches Eck / Haustürklingel
« am: 19. March 2012, 13:27 »
Die Haustüklingel an der Wand,
der Mädchenbusen in der Hand,
sind beides Dinge wohlverwandt!

Denn,  wenn man eines leis' berührt
man innen drinnen deutlich spürt,
dass unten draußen einer steht,
der sehnsuchtsvoll nach Einlass fleht.
12
Softwareentwicklung / Dokumentation
« am: 16. March 2012, 20:31 »
Kann mir jemand ein gutes Tool für die Dokumentation meiner Software empfehlen?
Es sollte natürlich gratis sein  :-D
13
Softwareentwicklung / QEMU - Debug-Messages an Gastsystem schicken
« am: 17. February 2012, 13:15 »
Ich würde gerne (und ich weiß, dass es geht - nur nicht wie) Debug-Messages an das Gastsystem schicken.
Und zwar über die VM an mein Ubuntu-Terminal um genau zu sein.

Hat da jemand schon Erfahrung damit? Verzeiht mir falls man das auch googeln kann, ich hab darüber nichts gefunden.
14
OS-Design / C oder C++
« am: 15. February 2012, 21:55 »
Lasst mal was hören Leute ^^

Ich persönlich steh ja absolut auf die Möglichkeit objektorientiert zu programmieren.

Gibts ein paar Tipps bzw Ratschläge die einem helfen können für welche Sprache
man sich konkret entscheidet?

:)
15
Softwareentwicklung / .intel_syntax
« am: 14. February 2012, 19:57 »
Hallo Leute,

ohne genug Erfahrung haben zu können und aus reiner eigener Präferenz würde
ich lieber die Intel-Syntax benützen als die AT&T.

Fürs erste hab ich Teil 4 des OS Tutorials gemacht und das funktioniert auch alles soweit.
Wenn ich aber die .intel_syntax Direktive verwende, dann funktioniert Hello World nicht mehr.

Funktioniert:
// ...
.global _start
    _start:
    mov $kernel_stack, %esp
    call init
// ...

Funktioniert nicht:
// ...
.global _start
    _start:
    .intel_syntax noprefix
    mov esp, kernel_stack
    call init
// ...

Kann mir da evenutell jemand verraten wie ich dem Assembler der korrekt beibringe?
Wäre super!

PS: Hallo übrigends Bin neu hier und heiße Stefan. Bin 24 aus Österreich/Kärnten und
studiere Informatik an der TU Graz. :)
Seiten: [1]

Einloggen