Autor Thema: Software Multitasking  (Gelesen 30694 mal)

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #100 am: 14. May 2009, 22:37 »
@PorkChicken: Du hast geschrieben, dass Du auch mein kernel.asm reduziert hast. Kannst Du das mal zeigen, oder hast Du ckernel.c gemeint?
jo, das kann ich. Ich hab zur Zeit keinen Zugriff auf den PC mit dem Code, aber ich hab das mal versucht zu rekonstruieren:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; HenkesSoft 0.07 (version from Apr 18, 2009) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org 0x8000     ; code's start offset
[BITS 16]     ; 16 Bit Code
[global RealMode]
[extern _main] ; this is in the c file

;;;;;;;;;;;;;
; Real Mode ;
;;;;;;;;;;;;;

RealMode:
    xor ax, ax         ; set up segments
    mov es, ax
    mov ds, ax
    mov ss, ax
    mov sp, ax

    mov si, welcome
    call print_string

    cli               ; clear interrupts

    lgdt [gdtr]       ; load GDT via GDTR (defined in file "gtd.inc")

; we actually only need to do this ONCE, but for now it doesn't hurt to do this more often when
; switching between RM and PM
    in  al, 0x92      ; switch A20 gate via fast A20 port 92
    cmp al, 0xff      ; if it reads 0xFF, nothing's implemented on this port
    je .no_fast_A20
   
    or  al, 2         ; set A20_Gate_Bit (bit 1)
    and al, ~1        ; clear INIT_NOW bit (don't reset pc...)
    out 0x92, al
    jmp .A20_done
   
.no_fast_A20:         ; no fast shortcut -> use the slow kbc...
    call empty_8042 
   
    mov al, 0xD1      ; kbc command: write to output port
    out 0x64, al
    call empty_8042
   
    mov al, 0xDF      ; writing this to kbc output port enables A20
    out 0x60, al
    call empty_8042

.A20_done:
    mov eax, cr0      ; switch-over to Protected Mode
    or  eax, 1        ; set bit 0 of CR0 register
    mov cr0, eax      ;

    jmp 0x8:ProtectedMode ; http://www.nasm.us/doc/nasmdo10.html#section-10.1
 
;;;;;;;;;
; Calls ;
;;;;;;;;;

empty_8042:
    call Waitingloop
    in al, 0x64
    cmp al, 0xff      ; ... no real kbc at all?
    je .done
   
    test al, 1        ; something in input buffer?
    jz .no_output
    call Waitingloop
    in al, 0x60       ; yes: read buffer
    jmp empty_8042    ; and try again
   
.no_output:
    test al, 2        ; command buffer empty?
    jnz empty_8042    ; no: we can't send anything new till it's empty
.done:
ret

print_string:
    mov ah, 0x0E
.loop_start:
    lodsb              ; grab a byte from SI
    test al, al        ; test AL
    jz .done           ; if the result is zero, get out
    int 0x10           ; otherwise, print out the character!
    jmp .loop_start
.done:
    ret


Waitingloop:                   
    mov ebx,0x9FFFF
.loop_start:
    dec ebx     
    jnz .loop_start
    ret       
   
;;;;;;;;;;;;;;;;;;
; Protected Mode ;
;;;;;;;;;;;;;;;;;;

[Bits 32]

ProtectedMode:
    mov    ax, 0x10
    mov    ds, ax      ; data descriptor --> data, stack and extra segment
    mov    ss, ax           
    mov    es, ax
    xor    eax, eax    ; null desriptor --> FS and GS
    mov    fs, ax
    mov    gs, ax
    mov    esp, 0x200000 ; set stack below 2 MB limit

  call _main ; ->-> C-Kernel
  jmp $
   
 

;;;;;;;;;;;
; Strings ;
;;;;;;;;;;;

welcome db 'HenkesSoft 0.07 (Apr 18, 2009)', 13, 10, 0

;;;;;;;;;;;;
; Includes ;
;;;;;;;;;;;;

%include "gdt.inc"
Hab noch die welcome-Nachricht drinne gelassen, und nur das nötigste für den Wechsel in den Protected Mode. Das erleichtert das Testen, wenn man nicht immer "pm" eintippen muss, und dann warten darf, bis der Bildschirm voll mit buntem Text ist ;)

Achja, die Waitingloop hab ich aus dem [bits 32]- in den [bits 16]-Teil geschoben. Es ist ziemlich riskant 32 Bit Code aus 16 Bit Code heraus aufzurufen. In diesem Fall wird folgendes ausgeführt:
00000000  BBFFFF            mov bx,0xffff
00000003  0900              or [bx+si],ax ; <--- Das sind die Überreste vom mov ebx, 0x0009ffff
00000005  4B                dec bx
00000006  75FD              jnz 0x5
00000008  C3                ret
Es kommt auf den Kontext an, ob die zusätzliche or-Instruktion problematisch ist, oder nicht ;)

@TheThing: Ich trenn mal dein Thema ab. Der Thread ist lang genug ;)
Dieser Text wird unter jedem Beitrag angezeigt.

ehenkes

  • Gast
Gespeichert
« Antwort #101 am: 16. May 2009, 00:57 »
Ich habe das Thema Software-Multitasking hier als kleines Kapitel im Tutorial verarbeitet:
http://www.henkessoft.de/OS_Dev/OS_Dev2.htm#mozTocId114565
Hoffentlich habe ich alles richtig beschrieben.

Beim Recherchieren habe ich noch folgendes Tutorial gefunden, das relativ ähnlich arbeitet, aber schon ausgefeiltere task-Strukturen und -Funktionen hat:
http://www.osdever.net/tutorials/multitasking.php

Danke nochmals an PortChicken! Auch für die verkürzte Variante von kernel.asm. Ich schleppe da mein viertel Tutorial mit mir nach.
« Letzte Änderung: 17. May 2009, 01:02 von ehenkes »

ehenkes

  • Gast
Gespeichert
« Antwort #102 am: 18. May 2009, 21:08 »
Ich habe da doch noch eine Nachfrage:

Bei mir sieht das nach Vorlage tyndur so aus:
    *(--kernel_stack) = 0x0200;       // eflags = interrupts aktiviert und iopl = 0
    *(--kernel_stack) = 0x08;         // cs
    *(--kernel_stack) = (ULONG)entry; // eip
    *(--kernel_stack) = 0;            // interrupt nummer
    *(--kernel_stack) = 0;            // error code

Im Intel Manual Vol. 3, 5-18 habe ich Folgendes gefunden:
Zitat
eflags, cs, eip, error code
Die Interrupt Nr. taucht da gar nicht auf.  :?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #103 am: 18. May 2009, 21:34 »
Jo, die Reihenfolge in den Kommentaren stimmt nicht.
Dieser Text wird unter jedem Beitrag angezeigt.

ehenkes

  • Gast
Gespeichert
« Antwort #104 am: 18. May 2009, 21:49 »
Also eflags, cs, eip, error code, interrupt nr? Warum steht da nix im Intel Manual von dieser Nr.?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #105 am: 18. May 2009, 21:54 »
Weil wir die Nummer selbst auf den Stack legen. Und das wiederrum tun wir, weil wir zu faul sind, 256 vollständige Interrupthandler zu schreiben. Lieber bloß jedem Interrupt einen 2- bis 3-zeiligen Stub geben, und dann zum richtigen Handler springen.
Dieser Text wird unter jedem Beitrag angezeigt.

ehenkes

  • Gast
Gespeichert
« Antwort #106 am: 18. May 2009, 21:56 »
Ah, nun wird das klar.  :-)

 

Einloggen