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 - middle_endian

Seiten: [1] 2
1
Lowlevel-Coding / Re: Problem mit inlineassambler und lidt
« am: 06. September 2007, 23:43 »
das tut was es soll :)
2
Lowlevel-Coding / Re: Problem mit inlineassambler und lidt
« am: 06. September 2007, 21:40 »
@MNemo: das hab ich auch versucht, allerdings gibts da auch einen internal compiler-error.
idt.cpp:57: internal compiler error: in emit_move_insn, at expr.c:3096
g++-version 4.0.3
3
Lowlevel-Coding / Re: Problem mit inlineassambler und lidt
« am: 05. September 2007, 17:44 »
welche gcc version verwendest du?
ich bekomm einen internal-compiler error.
4
Lowlevel-Coding / Re: keyboard eingabe, pic
« am: 30. July 2007, 13:20 »
ok ja, das macht sinn. aber im jetzigen zustand meines kernels lässt sich wenig am design der routine ändern bzw sollte diese vorgehensweise doch sogar die "vernünftigste" sein!?
5
Lowlevel-Coding / Re: keyboard eingabe, pic
« am: 30. July 2007, 10:41 »
hi,
da ich keinen neuen thread deswegen aufmachen wollte, stell ich die frage gleich hier. es geht um das prinzipielle design des keyboard treibers.
herzstück des treibers ist bei mir die handle_keystroke routine, die beim auftreten des irq1 aufgerufen wird. diese routine schreibt das übertragene zeichen in einen eigens angelegten puffer-bereich. die "user-level" routinen des treibers arbeiten nur noch mit diesem tastatur puffer.
getch sieht bei mir so aus:

;; ---------------------------------------------
;; read one character from the keyboard(buffer)
;; ---------------------------------------------
;; return value:
;; al = keyboard input character
;; temp. register = ebx
getch:
               ;; initialization stuff
               ;; ...

               ;; wait until data is available
.wait:
mov al, [key_buf_pos]
cmp [key_buf_beg], al ; wait for keyboard data
jne .ready
jmp .wait
.ready:

                ;; read data from keyboard buffer
                ;; ...
ret

funktionieren tut das ganze, nur stört mich diese schleife ein wenig, die kontinuierlich die cpu belastet und checkt, ob im puffer daten zur verfügung stehn. prinzipiell wäre das (im moment) kein problem, da die cpu zum zeitpunkt des abarbeitens von getch sowieso nichts anderes zu tun hat. auch im multi-process betrieb seh ich kein problem, da die getch routine in einem eigenen prozess aufgerufen wird, und dieser eben neben anderen prozessen vor sich herläuft.
trotzdem meine frage: gibts eine elegantere (effizientere) variante? mir fällt mit den zur verfügung stehenden mitteln nichts ein(mein kernel besitzt im moment lediglich funktionen zur textausgabe und eben den tastaturtreiber).
6
Lowlevel-Coding / Re: keyboard eingabe, pic
« am: 26. July 2007, 07:25 »
ok, hab jetzt den eoi code am ende der ersten beiden irq-handler(0 und 1) eingefügt. in meinen interrupt routinen geb ich wie gesagt aus, welcher interrupt gerade aufgerufen wurde.
jetzt bekomm ich natürlich ständig die irq0-meldung(timer) ausgegeben. das initialisieren der idt mit den handlern scheint also zu funktionieren. wenn ich allerdings eine taste drück, passiert mit irq1 immer noch nichts. erst nach 9-maligem drücken bekomm ich von bochs die meldung

[kbd ] internal keyboard buffer full. ignoring scancode(xy)
aber warum wird der handler nicht aufgerufen?

EDIT: habs hingekriegt. es war ein einfacher logischer fehler. danke für die hilfe :)
7
Lowlevel-Coding / Re: keyboard eingabe, pic
« am: 25. July 2007, 15:54 »
ändert leider auch nix :(
hab auch versucht kurz delays hinter die out instruktionen zu setzen. bringt auch nix.
8
Lowlevel-Coding / keyboard eingabe, pic
« am: 25. July 2007, 15:25 »
hi,
ich versuch mich gerade an einem tastaturtreiber. dazu hab ich die irqs des master/slave-pics auf die interrupts 20h-27h und 28h-2fh gemappt. soweit ich das richtig verstanden hab, wird bei einer tastatureingabe der irq1 aufgerufen (wobei danach auf port 0x60 der scancode abgelesen werden kann). dem irq1 ist bei mir die isr 21h zugeordnet. allerdings wird diese isr  nicht aufgerufen, wenn ich eine taste drücke.
jetzt frag ich mich, obs an der remapping routine liegt, oder an was anderem. hier der code den ich zum remappen verwende:

;; PIC ports
%define PIC_MASTER_CMD 20h
%define PIC_MASTER_DATA 21h
%define PIC_SLAVE_CMD 0a0h
%define PIC_SLAVE_DATA 0a1h

;; -----------------------------------------------
;; remapping PICs IRQs to not-reserved interrupts
;; -----------------------------------------------
remap_pic:
      ;; ICW1
      mov al, 10001b          ; bit1=1: forth ICW, bit2=0: pic cascading
      out PIC_MASTER_CMD, al
      out PIC_SLAVE_CMD, al

      ;; now starting to send the 3 inizialisation words on the data port
      ;;    ICW2: its vector offset
      ;;    ICW3: tell it how it is wired to master/slaves
      ;;    ICW4: gives additionnal infos about the environment

      ;; ICW2
      mov al, 20h
      out PIC_MASTER_DATA, al       ; map master irqs to int 20h-27h
      mov al, 28h
      out PIC_SLAVE_DATA, al        ; map slave ircq to 28h-2fh

      ;; ICW3
      mov al, 4                     ; 4 == bit3=1 -> irq2@master wired with slave ...
      out PIC_MASTER_DATA, al
      shr al, 2                     ; number of master irq necessary -> also irq2
      out PIC_SLAVE_DATA, al

      ;; ICW4
      ;; before isr finishes, the pic needs to be notified,
      ;; so he knows when to restart work
      mov al, 1
      out PIC_MASTER_DATA, al
      out PIC_SLAVE_DATA, al

      ;; end of interrupt(eoi) signal to both pics
      mov al, 20h
      out PIC_MASTER_CMD, al
      out PIC_SLAVE_CMD, al
      ret

wenn ich den irq1 per software-interrupt aufrufe, wird die entsprechende isr auch ausgeführt, was mich vermuten lässt, dass es nichts mit einer möglicherweise falschen initialisierung der idt zu tun.

meine allgemeine ablaufreihenfolge sieht so aus:

;; interrupts disabled
;; ...

pmode:
      ;; ...

      ;; init idt
      ;; ...

      call remap_pic
      call enable_irqs
      sti

      ;; kernel main
      ;; ...

kann mir jemand sagen, was da schief läuft?
9
hab jetzt allerdings noch ein problem mit der idt. meine isr wird nämlich nicht aufgerufen

%include "config32.asm"

[BITS 16]
org KERNEL_ADR << 4    ; internal multiplication by 16

start:
      cli
      mov ax, cs
      mov ds, ax           ; set ds to cs
      mov sp, STACK_ADR

   ;; set gdt
      lgdt [gdt_desc]
      mov eax, cr0
      or eax, 1
      mov cr0, eax
      jmp dword gdt_code:pmode   ; far jump reloads the cs register and flushes


[BITS 32]
pmode:
      ;; all register except of cs still contain 16bit values
      ;; -> put valid selectors into ds, ss and es
      ;; setup stack
      mov ax, gdt_data
      mov ds, ax
      mov ss, ax
      mov es, ax
      mov esp, STACK_ADR

      lidt [idt_desc]            ; load idt
      int 20h                     
      jmp $


;; ---------------------------
;; interrupt service routines
;; ---------------------------
void_isr
      mov eax, FRAME_BUFFER
      mov dword [eax], ':-( '
      jmp $
     
isr_test:
      mov eax, FRAME_BUFFER
      mov dword [eax], ':-) '
      iret
     

;; ------------------------
;; global descriptor table
;; ------------------------
;; 8B/descriptor, 8192 descriptors maximum -> 64KB max size
gdt:
      dd 0
      dd 0

gdt_code equ $-gdt
      dw 0ffffh         ; limit 0:15
      dw 0              ; base 0:15
      db 0              ; base 16:23
      db 10011010b      ; present, ring 0 priv(2bit), code segment, executable, non-conforming, readable
      db 11001111b      ; page-granular, 32-bit, ..., limit 16:19(1111)
      db 0              ; base 24:31

gdt_data equ $-gdt
      dw 0ffffh
      dw 0
      db 0
      db 10010010b      ; data segment(bit4)
      db 11001111b
      db 0
gdt_end:

;; gdt descriptor
gdt_desc:
      dw gdt_end-gdt-1
      dd gdt


;; ---------------------------
;; interrupt descriptor table
;; ---------------------------
;; idt descriptor
idt_desc:
      dw idt_end-idt-1
      dd idt

idt:
%rep 32
      dw void_isr    ;
      dw gdt_code    ; gdt selector
      db 0           ; always zero
      db 8eh         ; access, attributes
      dw 0           ; void_isr >> 16 == 0
%endrep

      dw isr_test
      dw gdt_code
      db 0
      db 8eh
      dw 0
idt_end:


;; kernel stack
;resd 128
;stack:

msg db "test message ..."
times ((2880*512-512)-($-$$)) db 0 ;

beim aufruf des interrupts springt er mir nach 0x8:0xfd55. er sollte allerdings nach 0x8:0x1003b springen.
der code ist vom prinzip her wieder mit dem früheren code, in dem alles im bootloader gemacht wurde, identisch.
was passt da jetzt schon wieder nicht?

EDIT: problem behoben. durch den sprung des kernels nach 0x10000 reicht das einfache zuweisen der isr in der idt nicht mehr aus, da ich mit 2B adressen nicht mehr auskomm. hab also nach dem laden der idt (testweise) folgendes gemacht:

      mov eax, isr_test
      mov [idt], ax
      shr eax, 16
      mov [idt+6], ax
10
siehe oben, war zu langsam beim editieren :)
11
der hund muss leider wo anders begraben liegen. selbst wenn ich den stack-bereich derart verkleinere (oder auf ne höhere adresse auslagere), dass die 512B grenze nicht überschritten wird, funktionierts nicht. auf das org 0x1000 ändert nichts.
fehlt mir vielleicht irgend eine initialisierung im kernel oder verändert sich durch den far jump vom bootloader in den kernel irgendwas, was vor dem laden der gdt berücksichtigt werden muss?

EDIT: habs jetzt hingekriegt. org 0x10000 zusammen mit dem korrekten setzen des datensegments am beginn des kernels haben gefehlt. also:
[BITS 16]
org KERNEL_ADR << 4   ; internal multiplication by 16

start:
      cli
      mov ax, cs
      mov ds, ax           ; set ds to cs
      mov sp, stack

  ;; set gdt
      lgdt [gdt_desc]
      mov eax, cr0
      or eax, 1
      mov cr0, eax
      jmp dword 0x8:pmode   ; far jump reloads the cs register and flushes

      ; ....
12
also hier der minimalistische bootloader
%include "config32.asm"

[BITS 16]
org 0x7c00

init:
                xor ax, ax
                mov ds, ax
                mov es, ax

mov ax, 0100h
mov ss, ax
mov ax, stack
mov sp, ax ; relative adressing to stack segment

mov [bootdrv], dl
                call load            ; load kernel

;; jump to kernel
mov ax, KERNEL_ADR
push ax
xor ax, ax
push ax
retf
     

;; kernel-loading routine
load:
push ds
mov ax, 0 ; reset function
mov dl, [bootdrv] ; what drive?
int 13h ; interrupt
pop ds
jc load

.loop0:
mov ax, KERNEL_ADR
mov es, ax ; buffer address for reading
xor bx, bx ;  offset = 0

;; read in sectors
mov ah, 2 ; read function
mov al, 1 ; 1 sectors
mov cx, 2 ; cylinder = 0, sector = 2
xor dx, dx ; head = 0, drive = 0
int 13h ; es:bx = 0x1000 (internal multiplication with 16)
jc .loop0
ret


bootdrv db 0

;; little realmode stack
         resd 64
stack:

times 510-($-$$) db 0
      dw 0aa55h
;; size = 512B

und hier der relevante teil vom kernel

%include "config32.asm"

[BITS 16]

start:
      ;; setup stack
      xor ax, ax
      mov ds, ax
      mov es, ax
      mov ds, ax
      mov esp, stack

  ;; set gdt
      cli
      lgdt [gdt_desc]
      mov eax, cr0
      or eax, 1
      mov cr0, eax
      jmp dword gdt_code:pmode   ; far jump reloads the cs register and flushes
                           ; the real-mode instructions from the prefetch queue     

[BITS 32]
pmode:
      ;; all register except of cs still contain 16bit values
      ;; -> put valid selectors into ds, ss and es
      ;; setup stack
      mov ax, gdt_data
      mov ds, ax
      mov ss, ax
      mov es, ax
      mov esp, stack

      lidt [idt_desc]            ; load idt

      ;; ...
      jmp $


;; ---------------------------
;; interrupt service routines
;; ---------------------------
void_isr
      mov eax, FRAME_BUFFER
      mov dword [eax], ':-( '
      jmp $
     
isr_test:
      mov eax, FRAME_BUFFER
      mov dword [eax], ':-) '
      iret



msg db "test message ..."

;; kernel stack
   resd 1024
stack:

;; ------------------------
;; global descriptor table
;; ------------------------
;; 8B/descriptor, 8192 descriptors maximum -> 64KB max size
gdt:
      dd 0
      dd 0

gdt_code equ $-gdt
      dw 0ffffh         ; limit 0:15
      dw 0              ; base 0:15
      db 0              ; base 16:23
      db 10011010b      ; present, ring 0 priv(2bit), code segment, executable, non-conforming, readable
      db 11001111b      ; page-granular, 32-bit, ..., limit 16:19(1111)
      db 0              ; base 24:31

gdt_data equ $-gdt
      dw 0ffffh
      dw 0
      db 0
      db 10010010b      ; data segment(bit4)
      db 11001111b
      db 0
gdt_end:

;; gdt descriptor
gdt_desc:
      dw gdt_end-gdt-1
      dd gdt

;; ---------------------------
;; interrupt descriptor table
;; ---------------------------
;; idt descriptor
idt_desc:
      dw idt_end-idt-1
      dd idt

idt:
%rep 32
      dw void_isr   
      dw gdt_code    ; gdt selector
      db 0           ; always zero
      db 8eh         ; access, attributes
      dw 0           ; void_isr >> 16 == 0
%endrep

      dw isr_test
      dw gdt_code
      db 0
      db 8eh
      dw 0
idt_end:

times ((2880*512-512)-($-$$)) db 0      ; complete floppy disk for bochs

der far-jump in den protected mode hat einen triple-fault zur folge.

00000904030e[CPU  ] fetch_raw_descriptor: GDT: index (f)1 > limit (0)
00000904030e[CPU  ] interrupt(): gate descriptor is not valid sys seg
00000904030e[CPU  ] interrupt(): gate descriptor is not valid sys seg
00000904030i[CPU  ] protected mode
00000904030i[CPU  ] CS.d_b = 16 bit
00000904030i[CPU  ] SS.d_b = 16 bit
00000904030i[CPU  ] | EAX=00000011  EBX=00000000  ECX=00130002  EDX=00000000
00000904030i[CPU  ] | ESP=00001137  EBP=00000000  ESI=000088f0  EDI=0000ffde
00000904030i[CPU  ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00000904030i[CPU  ] | SEG selector     base    limit G D
00000904030i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00000904030i[CPU  ] |  CS:1000( 1e00| 0|  0) 00010000 0000ffff 0 0
00000904030i[CPU  ] |  DS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00000904030i[CPU  ] |  SS:0100( 0000| 0|  0) 00001000 0000ffff 0 0
00000904030i[CPU  ] |  ES:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00000904030i[CPU  ] |  FS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00000904030i[CPU  ] |  GS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00000904030i[CPU  ] | EIP=00000020 (00000020)
00000904030i[CPU  ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00000904030i[CPU  ] | CR3=0x00000000 CR4=0x00000000
00000904030i[CPU  ] >> jmp far 0008:00000028 : 66EA280000000800
00000904030e[CPU  ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00000904030i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
00000904030e[CPU  ] CPU_LOOP bx_guard.interrupt_requested=1
Next at t=904030
(0) [0x00010020] 1000:0020 (unk. ctxt): jmp far 0008:00000028     ; 66ea280000000800
13
Lowlevel-Coding / protected-mode, kernel laden, reihenfolge
« am: 23. July 2007, 15:24 »
hi,
kurz zur ausgangslage. bis jetzt sieht der ablauf meines codes so aus:
- bootloader wird vom ersten sektor der diskette nach 0x7c00 geladen
- der kernel, der direkt hinter dem bootloader im zweiten sektor der diskette liegt, wird eingelesen
- lgdt [gdt_desc] wird ausgeführt
- jump in den protected-mode
- lidt [idt_desc] wird ausgeführt
- es wird zum zuvor geladenen kernel gesprungen
das funktioniert alles wunderbar. das problem ist jetzt folgendes. die interrupt service routinen sind bis jetzt natürlich im bootloader, da ich ja im bootloader die idt lade. nun würd ich aber gern das switchen in den protected mode, sowie das laden der gdt/idt in den kernel verlagern, damit ich meine interrupt-service-routinen im kernel definieren kann.
ich hab also den funktionierenden code hergenommen und anders auf bootloader und kernel verteilt. also:

bootloader:
- laden des kernels(nach 0x1000)
- springen zum kernel

kernel:
- interrupts deaktivieren
- lgdt [gdt_desc]                  <-- nach diesem befehl steht im gdt-register nichts drinnen(base=0, limit=0)
- jump in den protected mode (funktioniert damit natürlich nicht)
was stimmt da nicht?
würde diese "neue" reihenfolge der ausführung überhaupt funktionieren bzw macht sie sinn?
14
Lowlevel-Coding / protected-mode, idt, interrupts
« am: 20. July 2007, 10:57 »
hi,
ein neues problem macht mir zu schaffen. und zwar gehts um das laden der interrupt descriptor table und das zuweisen einer interrupt service routine. hab bis jetzt nur einen eintrag für den interrupt 0 in meiner idt. wenn ich den interrupt im code aufrufe, rebootet bochs ohne in die interrupt service routine zu springen.
%include "config32.asm"

[BITS 16]
org 0x7c00

init:
      xor ax, ax
      mov ds, ax
      mov es, ax

      mov ax, 0100h
      mov ss, ax
      mov ax, STACK_ADR
      mov sp, ax ; relative adressing to stack segment


      ;; set gdt
      cli                                       ; disable interrupts
      lgdt [gdt_desc]
      mov eax, cr0
      or eax, 1
      mov cr0, eax
      jmp gdt_code:pmode


[BITS 32]
pmode:
      mov ax, gdt_data
      mov ds, ax
      mov ss, ax
      mov es, ax
      mov esp, STACK_ADDRESS

      ;; fill up idt
      lidt [idt_desc]            ; load idt
      mov eax, isr0           
      mov [idt], ax             ; assign lower word
      shr eax, 16               
      mov [idt+6], ax         ; assign upper word   (**)
      sti                             ; reenable interrupts
      int 0                          ; interrupt


isr0:
   cli
   hlt
   iret


;; -----------------------------
;; global descriptor table
;; -----------------------------
gdt:
      dd 0
      dd 0

gdt_code equ $-gdt
      dw 0ffffh
      dw 0
      db 0
      db 10011010b
      db 11001111b
      db 0

gdt_data equ $-gdt
      dw 0ffffh
      dw 0
      db 0
      db 10010010b
      db 11001111b
      db 0
gdt_end:

;; gdt descriptor
gdt_desc:
      dw gdt_end-gdt-1
      dd gdt
     
;; --------------------------------
;; interrupt descriptor table
;; --------------------------------
;; idt descriptor
idt_desc:
      dw idt_end-idt-1
      dd idt

idt:
      dw 0                 ; filled up at runtime: isr0 & ffffh
      dw gdt_code    ; gdt selector
      dw 8e00h         ; access, attributes
      dw 0                 ; filled up at runtime: isr0 >> 16
idt_end:

times 510-($-$$) db 0
      dw 0aa55h
;; size = 512B


über den inhalt von idt meint bochs:

<bochs:29> info idt 0
Interrupt Descriptor Table (base=0x00007cb6):
IDT[0x00]=??? descriptor hi=0x00000000, lo=0x00087c7e

wo könnte das problem begraben liegen?

EDIT: argl, hatte bei (**) vorher 4 statt 6 stehn. dadurch hab ich mir natürlich die access/attribut-flags zerschossen.
bitte posting entweder löschen, oder falls der code hilfreich erscheint halt einfach stehn lassen :)
15
Lowlevel-Coding / Re: bochs debug-problem
« am: 18. July 2007, 22:59 »
der eingebaute. den ich fälschlicherweise als nicht vorhanden abgestempelt hab, und gdb dafür die schuld gegeben hab.
16
Lowlevel-Coding / Re: bochs debug-problem
« am: 18. July 2007, 21:03 »
Ich nutze meistens den bochs debuger, bochs logs, disassemblies, stacktraces, "cli-hlt", printf/cout.
wie startest du unter linux diesen bochs-internen debugger?

edit: halleluja, nachdem ich bochs ein zweites mal mit den korrekten parametern kompiliert hab, funktioniert das debuggen jetzt endlich!
17
Lowlevel-Coding / Re: bochs debug-problem
« am: 18. July 2007, 14:28 »
ok, hab jetzt einen mini 32bit assembler kernel, der von meinem bootloader geladen wird. debuggen geht aber immer noch nicht...
da ich in dieser hinsicht scheinbar dauernd mit dem kopf gegen die wand renne, würd mich einfach (etwas allgemeiner gesehn) interessiern, wie ihr euren kernel unter linux debugged(kein c, nur assembler code)?!
18
Lowlevel-Coding / Re: bochs debug-problem
« am: 16. July 2007, 15:21 »
sprich, wenn ich mich in den protected-mode einlese und diesen verwende, funktioniert das debuggen mittels gdb?
19
Lowlevel-Coding / Re: bochs debug-problem
« am: 16. July 2007, 08:44 »
hi,
ich hab mir dieses wochenende noch ein ganzes weilchen den kopf darüber zerbrochen, wie ich meinen code unter linux debuggen kann, aber da ich mit qemu/gdb bzw bochs/gdb einfach nicht weiterkomm(offenbar kann gdb mit dem 16bit code ohne debuginfos genau gar nichts anfangen) frag ich mich, wie ihr euren code unter linux debugged?
weiß außerdem vielleicht jemand was bochs unter windows intern für nen debugger verwendet? hab eigentlich angenehmen, dass gdb verwendet wird, aber da das debuggen unter windows funktioniert - es aber wenn ich den gdb unter windows mit bochs quasi standalone verwendet nicht funktioniert - hab ich diesen gedanken wieder verworfen.
20
Lowlevel-Coding / Re: bochs debug-problem
« am: 13. July 2007, 14:13 »
Setz einen Breakpoint in deinen Kernel und laß dann erstmal weiterlaufen.
und wie stell ich das an? hab versucht vor dem ersten befehl im kernel int 3 bzw 0xcc aufzurufen, aber das versetzt mich auch nicht in den debugger.
unter windows läuft das debugging mit bochs wunderbar. lieber wärs mir, wenns umgekehrt wär :)
Seiten: [1] 2

Einloggen