Eigenes OS?
-
Erhard Henkes schrieb:
... statt nasm GNU as zu verwenden, weiss aber jetzt nicht genau, ob man 16-Bit Assembler Quellcode mit as assemblieren kann. Vorteil davon wäre noch, dass man nur ein Tool bräuchte: DJGGP. GNU as ist nämlich in DJGPP mitenthalten.
Habe mir die Syntax von as bisher noch nicht angeschaut. AT&T?
Ja, AT&T Syntax mit dem Nachteil von links nach rechts Lesen, so wie man es normalerweise jahrelange macht, und dem Haufen Intel-Doku, wo man von rechts nach links lesen muss. Aber Lesbarkeit scheint ja sowieso der Punkt zu sein, auf den ich hier alleine bestehe.
Ich habe mal aus Neugier die Assembler-Dateien boot.asm, kernel.asm und isr.asm nach AT&T umgesetzt und erfolgreich versucht, einmal allein mit DJGPP (im Sinne ohne nasm) und einmal mit mingw Tools eine funktionierende MyOS.bin zu bauen. Nicht, dass ich darauf bestehe, vollständig auf diese Tools umzusteigen. Ist nur "Machbarkeitsstudie". Mein Makefile dazu sieht so aus:
all: @echo Select target: mingw or djgpp. @echo Exit. djgpp: @echo Building with djgpp: c:\djgpp\bin\as boot.s -o boot.o c:\djgpp\bin\ld boot.o -Ttext 0x7C00 -e _start -o boot.exe c:\djgpp\bin\objcopy --strip-all --only-section .text --output-target binary boot.exe boot.bin c:\djgpp\bin\as kernel.s -o kernel.o c:\djgpp\bin\as isr.s -o isr.o c:\djgpp\bin\gcc -Wall -c ckernel.c -o ckernel.o -O1 c:\djgpp\bin\gcc -Wall -c video.c -o video.o -O1 c:\djgpp\bin\gcc -Wall -c math.c -o math.o -O1 c:\djgpp\bin\gcc -Wall -c util.c -o util.o -O1 c:\djgpp\bin\gcc -Wall -c gdt.c -o gdt.o c:\djgpp\bin\gcc -Wall -c idt.c -o idt.o c:\djgpp\bin\gcc -Wall -c isrs.c -o isrs.o c:\djgpp\bin\gcc -Wall -c irq.c -o irq.o c:\djgpp\bin\gcc -Wall -c timer.c -o timer.o c:\djgpp\bin\gcc -Wall -c keyboard.c -o keyboard.o c:\djgpp\bin\ld -T kernel.ld kernel.o isr.o ckernel.o video.o gdt.o idt.o isrs.o irq.o util.o math.o timer.o keyboard.o -o ckernel.bin cmd /c copy /b boot.bin + ckernel.bin MyOS cmd /c del MyOS.bin cmd /c rename MyOS MyOS.bin cmd /c erase ..\MyOS.bin cmd /c copy MyOS.bin ..\MyOS.bin mingw: @echo Building with mingw: as boot.s -o boot.o ld boot.o -Ttext 0x7C00 -e _start -o boot.exe objcopy --strip-all --only-section .text --output-target binary boot.exe boot2.bin dd if=boot2.bin of=boot.bin bs=512 count=1 as kernel.s -o kernel.o as isr.s -o isr.o gcc -Wall -c ckernel.c -o ckernel.o -O1 -s gcc -Wall -c video.c -o video.o -O1 -s gcc -Wall -c math.c -o math.o -O1 -s gcc -Wall -c util.c -o util.o -O1 -s gcc -Wall -c gdt.c -o gdt.o -s gcc -Wall -c idt.c -o idt.o -s gcc -Wall -c isrs.c -o isrs.o -s gcc -Wall -c irq.c -o irq.o -s gcc -Wall -c timer.c -o timer.o -s gcc -Wall -c keyboard.c -o keyboard.o -s ld -Ttext 0x8000 -e _start kernel.o isr.o ckernel.o video.o gdt.o idt.o isrs.o irq.o util.o math.o timer.o keyboard.o -o ckernel.exe objcopy --strip-all --output-target binary ckernel.exe ckernel.bin cmd /c copy /b boot.bin + ckernel.bin MyOS cmd /c del MyOS.bin cmd /c rename MyOS MyOS.bin cmd /c erase ..\MyOS.bin cmd /c copy MyOS.bin ..\MyOS.bin
Das einzige Programm, das nicht Teil von DJGPP und mingw ist, ist dd. Ich weiss nicht, wie man unter WinXP eine fest definierte Anzahl von Bytes aus einer Datei in eine andere kopieren kann, also habe ich dd benutzt, was ja von *nix stammt. Wie dem auch sei, so scheint zu gehen, ohne nasm...
Ein Nachteil bezüglich mingw ist noch, dass AntiVir bei von mingw as erzeugten Dateien meckert, sind angeblich irgendwelche Trojanische PferdeErhard Henkes schrieb:
Was abc.w anspricht ist mein Hin- und Herhüpfen zwischen C-Code (vor allem zum Thema Interrupts) und isr.asm.
Genauer meine ich, dass der gcc spezifische inline-Code in den c-Dateien nicht schön ist, weil, nun, sehr gcc spezifisch...
-
Kann GAS nicht inzwischen auch Intel-Syntax? Das wuerde die Sache sicher vereinfachen.
-
Erhard Henkes schrieb:
Ja, gute Idee, habe es umgesetzt. Thanks @ +fricky.
keine ursache. später aber, wenn du mal multitasking machen willst, kannste die funktion so nicht mehr verwenden. dann besser einen counter in den 'task control block' (der struct, die den zustand einer task kontrolliert) einbauen, und beim warten nicht einfach rechenzeit verbraten, sondern zur nächten task weiterschalten (plus einer möglichkeit, den 'wait' abbrechen zu können, z.b. von einer anderen task oder aus einem interrupt).
-
Nobuo T schrieb:
Kann GAS nicht inzwischen auch Intel-Syntax? Das wuerde die Sache sicher vereinfachen.
echt, ne? diese bescheuerte at&t-syntax würde mich auch völlig nerven. welcher gehirnamputierte hat sich das bloss ausgedacht?
-
boot.asm, kernel.asm und isr.asm nach AT&T umgesetzt
Würdest Du mir diese Files bitte schicken oder - noch besser - hier posten? Damit ich die AT&T Syntax endlich besser lerne, denn isr.asm könnte man vielleicht auch weitgehend oder völlig in den C-Modulen aufgehen lassen, falls das bezüglich Ordnung mehr Sinn macht. Für mich ist z.B. die Intel Syntax eindeutig besser lesbar.
Das sieht doch irgendwie unnötig kompliziert aus:
static void idt_load(){ asm volatile("lidt %0" : "=m" (idt_register)); } // load IDT register (IDTR)
Das einzige Programm, das nicht Teil von DJGPP und mingw ist, ist dd. Ich weiss nicht, wie man unter WinXP eine fest definierte Anzahl von Bytes aus einer Datei in eine andere kopieren kann.
Nicht-Linux-User kennen dd nicht, verwenden partcopy (das ist, was Du anstelle dd suchst) oder rawwrite.
Ich bin da aber flexibel, nur möchte ich alles auf MS Windows ermöglichen, was ja bisher keinerlei Problem ist.
Ich möchte auch den Hinweis auf gvim (am Anfang fand ich das nicht uninteressant , weil OSDEV bezüglich des Flairs eher archaische Instrumente benötigt. ) verwerfen, weil notepad++ besser aussieht und weniger störrisch ist. Seht ihr das ähnlich?
-
+fricky schrieb:
Nobuo T schrieb:
Kann GAS nicht inzwischen auch Intel-Syntax? Das wuerde die Sache sicher vereinfachen.
echt, ne? diese bescheuerte at&t-syntax würde mich auch völlig nerven. welcher gehirnamputierte hat sich das bloss ausgedacht?
Total!
Wahrscheinlich irgendein weltfremder, idealistischer, langhaariger Linux-Frickler mit Strick-Polunder und Taxischein.Erhard Henkes schrieb:
Ich möchte auch den Hinweis auf gvim (am Anfang fand ich das nicht uninteressant , weil OSDEV bezüglich des Flairs eher archaische Instrumente benötigt. ) verwerfen, weil notepad++ besser aussieht und weniger störrisch ist. Seht ihr das ähnlich?
Wie ich das sehe, kann man sich vielleicht denken.
-
Erhard Henkes schrieb:
Ich möchte auch den Hinweis auf gvim (am Anfang fand ich das nicht uninteressant , weil OSDEV bezüglich des Flairs eher archaische Instrumente benötigt. ) verwerfen, weil notepad++ besser aussieht und weniger störrisch ist. Seht ihr das ähnlich?
klar, wenn man assembler-code auf tiefster low-level ebene schreibt, muss man noch lange keine prähistorischen tools verwenden.
-
Bezüglich der Assembler-Dateien in AT&T, die Kommentare sind alle unverändert. boot.s (hier habe ich, glaube, nur die Anzahl der Sektoren auf 40 geändert):
.global _start .section .text .code16 .equ kernel_start, _start + 1024 ################################## # setup a stack and segment regs # ################################## _start: xorw %ax, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss movw %ax, %sp ################################ # read kernel from floppy disk # ################################ movb %dl, bootdrive # boot drive stored by BIOS in DL. # we save it to [bootdrive] to play for safety. load_kernel: xorw %ax, %ax # mov ax, 0 => function "reset" int $0x13 jc load_kernel # trouble? try again mov $0x8000, %bx # set up start address of kernel # set parameters for reading function # 8-bit-wise for better overview movb bootdrive, %dl # select boot drive mov $40, %al # read 40 sectors mov $0, %ch # cylinder = 0 mov $2, %cl # sector = 2 mov $0, %dh # head = 0 mov $2, %ah # function "read" int $0x13 jc load_kernel # trouble? try again # show loading message mov $loadmsg, %si call print_string ################## # jump to kernel # ################## jmp kernel_start # address of kernel. "jmp bx" might also work. ####################### # call "print_string" # ####################### print_string: mov $0x0E, %ah # VGA BIOS fnct. 0x0E: teletype 1: lodsb # grab a byte from SI testb %al, %al # NUL? jz 2f # if the result is zero, get out int $0x10 # otherwise, print out the character! jmp 1b 2: ret ######## # data # ######## bootdrive: .byte 0 # boot drive loadmsg: .asciz "bootloader message: loading kernel ...\n\r" . = _start + 510 .byte 0x55 .byte 0xAA .end
Die Datei kernel.s:
############################################### # HenkesSoft 0.04 (version from Mar 26, 2009) # ############################################### .global RealMode .global _start .section .text .code16 ############# # Real Mode # ############# _start: RealMode: xorw %ax, %ax # set up segments mov %ax, %es mov %ax, %ds mov %ax, %ss mov %ax, %sp mov $welcome, %si call print_string addw $-0x40, %sp # make room for input buffer (64 chars) loop_start: mov $prompt, %si # show prompt call print_string mov %sp, %di # get input call get_string jcxz loop_start # blank line? -> yes, ignore it mov %sp, %si mov $cmd_hi, %di # "hi" command call strcmp je helloworld mov %sp, %si mov $cmd_help, %di # "help" command call strcmp je help mov %sp, %si mov $cmd_questionmark, %di # "?" command call strcmp je help mov %sp, %si mov $cmd_exit, %di # "exit" command call strcmp je exit mov %sp, %si mov $cmd_pm, %di # "pm (protected mode)" command call strcmp je pm mov $badcommand, %si # unknown command call print_string jmp loop_start helloworld: mov $msg_helloworld, %si call print_string jmp loop_start help: mov $msg_help, %si call print_string jmp loop_start exit: mov $msg_exit, %si call print_string xorw %ax, %ax int $0x16 # Wait for keystroke jmp $0xffff, $0x0000 # Reboot pm: call clrscr mov $msg_pm, %si call print_string call Waitingloop cli # clear interrupts lgdt gdtr # load GDT via GDTR # 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 inb $0x92, %al # switch A20 gate via fast A20 port 92 cmpb $0xFF, %al # if it reads 0xFF, nothing's implemented on this port je 1f orb $2, %al # set A20_Gate_Bit (bit 1) andb $0xFE, %al # clear INIT_NOW bit (don't reset pc...) outb %al, $0x92 jmp 2f 1: # no fast shortcut -> use the slow kbc... call empty_8042 movb 0xD1, %al # kbc command: write to output port outb %al, $0x64 call empty_8042 movb $0xDF, %al # writing this to kbc output port enables A20 outb %al, $0x60 call empty_8042 2: mov %cr0, %eax # switch-over to Protected Mode orl $1, %eax # set bit 0 of CR0 register movl %eax, %cr0 jump_to_protected_mode: ljmp $8, $ProtectedMode ######### # Calls # ######### empty_8042: call Waitingloop inb $0x64, %al cmpb $0xFF, %al # ... no real kbc at all? je 1f testb $1, %al # something in input buffer? jz 2f call Waitingloop inb $0x60, %al # yes: read buffer jmp empty_8042 # and try again 2: testb $2, %al # command buffer empty? jnz empty_8042 # no: we can't send anything new till it's empty 1: ret print_string: movb $0x0E, %ah 1: lodsb # grab a byte from SI testb %al, %al # test AL jz 2f # if the result is zero, get out int $0x10 # otherwise, print out the character! jmp 1b 2: ret get_string: xorw %cx, %cx 1: xorw %ax, %ax int $0x16 # wait for keypress cmpb $8, %al # backspace pressed? je 2f # yes, handle it cmpb $13, %al # enter pressed? je 3f # yes, we're done cmpb $63, %cl # 63 chars inputted? je 1b # yes, only let in backspace and enter movb $0x0E, %ah int $0x10 # print out character stosb # put character in buffer inc %cx jmp 1b 2: jcxz 1b # zero? (start of the string) if yes, ignore the key dec %di movb $0, (%di) # delete character dec %cx # decrement counter as well movb $0x0E, %ah int $0x10 # backspace on the screen movb $32, %al int $0x10 # blank character out movb $8, %al int $0x10 # backspace again jmp 1b # go to the main loop 3: movb $0, (%di) # null terminator movw $0x0E0D, %ax int $0x10 movb $0x0A, %al int $0x10 # newline ret strcmp: 1: movb (%si), %al # grab a byte from SI cmpb (%di), %al # are SI and DI equal? jne 2f # no, we're done. testb %al, %al # zero? jz 2f # yes, we're done. inc %di # increment DI inc %si # increment SI jmp 1b # loop! 2: ret clrscr: movw $0x0600, %ax xorw %cx, %cx mov $0x174F, %dx mov $0x07, %bh int $0x10 ret ################## # Protected Mode # ################## .section .text .code32 .p2align 4 ProtectedMode: movw $0x10, %ax mov %ax, %ds # data descriptor --> data, stack and extra segment mov %ax, %ss mov %ax, %es xorl %eax, %eax # null desriptor --> FS and GS mov %ax, %fs mov %ax, %gs mov $0x200000, %esp # set stack below 2 MB limit call clrscr_32 movb $0x01, %ah 1: call Waitingloop incb %ah andb $0x0F, %ah mov $msg_pm2, %esi # 'OS currently uses Protected Mode.' call PutStr_32 cmpl $(25 * 80 * 2 + 0xB8000), PutStr_Ptr jb 1b movl $0xB8000, PutStr_Ptr # text pointer wrap-arround call _kernel_main # ->-> C-Kernel jmp . Waitingloop: mov $0x9FFFF, %ebx 1: dec %ebx jnz 1b ret PutStr_32: movl PutStr_Ptr, %edi 1: lodsb testb %al, %al jz 2f stosw jmp 1b 2: movl %edi, PutStr_Ptr ret clrscr_32: movl $0xb8000, %edi movl %edi, PutStr_Ptr movl $1000, %ecx movl $0x07200720, %eax rep stosl ret PutStr_Ptr: .long 0xb8000 # You load the address you want to output to in [PutStr_Ptr], # the address of the string (has to be NUL terminated) # you want to print in esi and the attributes in ah # lodsb loads one byte from esi into al, then increments esi, # then it checks for a NUL terminator, # then it moves the char into the write position in video memory, # then increments edi and writes the attributes, # loops until it finds NUL pointer at which point it breaks ... ########### # Strings # ########### welcome: .asciz "HenkesSoft 0.05 (test version from Apr 03, 2009)\n\r" msg_helloworld: .asciz "Hello World!\n\r" badcommand: .asciz "Command unknown.\n\r" prompt: .asciz ">" cmd_hi: .asciz "hi" cmd_help: .asciz "help" cmd_questionmark: .asciz "?" cmd_exit: .asciz "exit" cmd_pm: .asciz "pm" msg_help: .asciz "Commands: hi, help, ?, pm, exit\n\r" msg_exit: .asciz "Reboot starts now. Enter keystroke, please.\n\r" msg_pm: .asciz "Switch-over to Protected Mode.\n\r" msg_pm2: .asciz "OS currently uses Protected Mode. " ############ # Includes # ############ ################################### ## Global Descriptor Table (GDT) ## ################################### NULL_Desc: .long 0 .long 0 CODE_Desc: .word 0xFFFF # segment length bits 0-15 ("limit") .word 0 # segment base byte 0,1 .byte 0 # segment base byte 2 .byte 0b10011010 # access rights .byte 0b11001111 # bit 7-4: 4 flag bits: granularity, default operation size bit, 2 bits available for OS # bit 3-0: segment length bits 16-19 .byte 0 # segment base byte 3 DATA_Desc: .word 0xFFFF # segment length bits 0-15 .word 0 # segment base byte 0,1 .byte 0 # segment base byte 2 .byte 0b10010010 # access rights .byte 0b11001111 # bit 7-4: 4 flag bits: granularity, big bit (0=USE16-Segm., 1=USE32-Segm.), 2 bits avail. # bit 3-0: segment length bits 16-19 .byte 0 # segment base byte 3 gdtr: Limit: .word 24 # length of GDT Base: .long NULL_Desc # base of GDT ( linear address: RM Offset + Seg<<4 )
Die Datei isr.s:
# Interrupt Service Routine isr0 ... isr32 .global _isr0 .global _isr1 .global _isr2 .global _isr3 .global _isr4 .global _isr5 .global _isr6 .global _isr7 .global _isr8 .global _isr9 .global _isr10 .global _isr11 .global _isr12 .global _isr13 .global _isr14 .global _isr15 .global _isr16 .global _isr17 .global _isr18 .global _isr19 .global _isr20 .global _isr21 .global _isr22 .global _isr23 .global _isr24 .global _isr25 .global _isr26 .global _isr27 .global _isr28 .global _isr29 .global _isr30 .global _isr31 .global _irq0 .global _irq1 .global _irq2 .global _irq3 .global _irq4 .global _irq5 .global _irq6 .global _irq7 .global _irq8 .global _irq9 .global _irq10 .global _irq11 .global _irq12 .global _irq13 .global _irq14 .global _irq15 .section .text # 0: Divide By Zero Exception _isr0: cli pushl $0 pushl $0 jmp isr_common_stub # 1: Debug Exception _isr1: cli pushl $0 pushl $1 jmp isr_common_stub # 2: Non Maskable Interrupt Exception _isr2: cli pushl $0 pushl $2 jmp isr_common_stub # 3: Int 3 Exception _isr3: cli pushl $0 pushl $3 jmp isr_common_stub # 4: INTO Exception _isr4: cli pushl $0 pushl $4 jmp isr_common_stub # 5: Out of Bounds Exception _isr5: cli pushl $0 pushl $5 jmp isr_common_stub # 6: Invalid Opcode Exception _isr6: cli pushl $0 pushl $6 jmp isr_common_stub # 7: Coprocessor Not Available Exception _isr7: cli pushl $0 pushl $7 jmp isr_common_stub # 8: Double Fault Exception (With Error Code!) _isr8: cli pushl $8 jmp isr_common_stub # 9: Coprocessor Segment Overrun Exception _isr9: cli pushl $0 pushl $9 jmp isr_common_stub # 10: Bad TSS Exception (With Error Code!) _isr10: cli pushl $10 jmp isr_common_stub # 11: Segment Not Present Exception (With Error Code!) _isr11: cli pushl $11 jmp isr_common_stub # 12: Stack Fault Exception (With Error Code!) _isr12: cli pushl $12 jmp isr_common_stub # 13: General Protection Fault Exception (With Error Code!) _isr13: cli pushl $13 jmp isr_common_stub # 14: Page Fault Exception (With Error Code!) _isr14: cli pushl $14 jmp isr_common_stub # 15: Reserved Exception _isr15: cli pushl $0 pushl $15 jmp isr_common_stub # 16: Floating Point Exception _isr16: cli pushl $0 pushl $16 jmp isr_common_stub # 17: Alignment Check Exception _isr17: cli pushl $0 pushl $17 jmp isr_common_stub # 18: Machine Check Exception _isr18: cli pushl $0 pushl $18 jmp isr_common_stub # 19: Reserved _isr19: cli pushl $0 pushl $19 jmp isr_common_stub # 20: Reserved _isr20: cli pushl $0 pushl $20 jmp isr_common_stub # 21: Reserved _isr21: cli pushl $0 pushl $21 jmp isr_common_stub # 22: Reserved _isr22: cli pushl $0 pushl $22 jmp isr_common_stub # 23: Reserved _isr23: cli pushl $0 pushl $23 jmp isr_common_stub # 24: Reserved _isr24: cli pushl $0 pushl $24 jmp isr_common_stub # 25: Reserved _isr25: cli pushl $0 pushl $25 jmp isr_common_stub # 26: Reserved _isr26: cli pushl $0 pushl $26 jmp isr_common_stub # 27: Reserved _isr27: cli pushl $0 pushl $27 jmp isr_common_stub # 28: Reserved _isr28: cli pushl $0 pushl $28 jmp isr_common_stub # 29: Reserved _isr29: cli pushl $0 pushl $29 jmp isr_common_stub # 30: Reserved _isr30: cli pushl $0 pushl $30 jmp isr_common_stub # 31: Reserved _isr31: cli pushl $0 pushl $31 jmp isr_common_stub # Common ISR stub saves processor state, sets up for kernel mode segments, calls the C-level fault handler, # and finally restores the stack frame. isr_common_stub: pusha push %ds push %es push %fs push %gs mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs mov %esp, %eax push %eax mov $_fault_handler, %eax call *%eax pop %eax pop %gs pop %fs pop %es pop %ds popa add $8, %esp iret # 32: IRQ0 _irq0: cli pushl $0 pushl $32 jmp irq_common_stub # 33: IRQ1 _irq1: cli pushl $0 pushl $33 jmp irq_common_stub # 34: IRQ2 _irq2: cli pushl $0 pushl $34 jmp irq_common_stub # 35: IRQ3 _irq3: cli pushl $0 pushl $35 jmp irq_common_stub # 36: IRQ4 _irq4: cli pushl $0 pushl $36 jmp irq_common_stub # 37: IRQ5 _irq5: cli pushl $0 pushl $37 jmp irq_common_stub # 38: IRQ6 _irq6: cli pushl $0 pushl $38 jmp irq_common_stub # 39: IRQ7 _irq7: cli pushl $0 pushl $39 jmp irq_common_stub # 40: IRQ8 _irq8: cli pushl $0 pushl $40 jmp irq_common_stub # 41: IRQ9 _irq9: cli pushl $0 pushl $41 jmp irq_common_stub # 42: IRQ10 _irq10: cli pushl $0 pushl $42 jmp irq_common_stub # 43: IRQ11 _irq11: cli pushl $0 pushl $43 jmp irq_common_stub # 44: IRQ12 _irq12: cli pushl $0 pushl $44 jmp irq_common_stub # 45: IRQ13 _irq13: cli pushl $0 pushl $45 jmp irq_common_stub # 46: IRQ14 _irq14: cli pushl $0 pushl $46 jmp irq_common_stub # 47: IRQ15 _irq15: cli pushl $0 pushl $47 jmp irq_common_stub irq_common_stub: pusha push %ds push %es push %fs push %gs mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs mov %esp, %eax push %eax mov $_irq_handler, %eax call *%eax pop %eax pop %gs pop %fs pop %es pop %ds popa add $8, %esp iret
Nicht zu lange draufgucken, schadet den Augen
-
Erhard Henkes schrieb:
Das einzige Programm, das nicht Teil von DJGPP und mingw ist, ist dd. Ich weiss nicht, wie man unter WinXP eine fest definierte Anzahl von Bytes aus einer Datei in eine andere kopieren kann.
Nicht-Linux-User kennen dd nicht, verwenden partcopy (das ist, was Du anstelle dd suchst) oder rawwrite.
Ich bin da aber flexibel, nur möchte ich alles auf MS Windows ermöglichen, was ja bisher keinerlei Problem ist.Ich habe grade geguckt, woher ich dd auf meinem System habe... aus dem Verzeichnis C:\Compiler\WinAVR-20081205\utils\bin. Nicht schön. Benutze ein Programm und weiss überhaupt nicht, woher ich es habe. Das kommt davon, wenn man die PATH Variable einfach mal so modifiziert...
Erhard Henkes schrieb:
Ich möchte auch den Hinweis auf gvim (am Anfang fand ich das nicht uninteressant , weil OSDEV bezüglich des Flairs eher archaische Instrumente benötigt. ) verwerfen, weil notepad++ besser aussieht und weniger störrisch ist. Seht ihr das ähnlich?
Ich benutze in letzter Zeit ausschliesslich gvim...
-
Nobuo T schrieb:
+fricky schrieb:
Nobuo T schrieb:
Kann GAS nicht inzwischen auch Intel-Syntax? Das wuerde die Sache sicher vereinfachen.
echt, ne? diese bescheuerte at&t-syntax würde mich auch völlig nerven. welcher gehirnamputierte hat sich das bloss ausgedacht?
Total!
Wahrscheinlich irgendein weltfremder, idealistischer, langhaariger Linux-Frickler mit Strick-Polunder und Taxischein.Ich glaube, AT&T Syntax ist älter als Linux und Intel und GNU zusammen. Ich sehe es so, dass allein aus der Tatsache, dass diese Syntax noch nicht "ausgestorben" ist und eine so lange Periode überdauert hat, muss etwas dahinter stecken. Ich hatte mich am Anfang auch wegen % und $ unbehaglich gefühlt, aber jetzt, sooo schlimm ist das nicht und die Syntax finde ich durchdachter und konsequenter in jeder Hinsicht als jede andere. Wenn wir hier in diesem Thread zurückschauen, wieviele Probleme gab es mit jmp und wieviel Ungewissheit, zumindest bei mir, ob jmp word oder jmp dword, nur weil nasm sowohl das eine als auch das andere erlaubt...
-
@abc.w: Danke für die Übersetzung von Intel nach AT&T und für das DJGPP / mingw makefile. Es sollte nicht von zu vielen Kleinigkeiten und/oder Geschmacksachen abhängen, ob jemand den Zugang zu OSDEV findet.
-
Nun können System Clock und Keyboard unabhängig den Bildschirm beschmutzen. Die vielen Polling-Endlosschleifen wurden nun gebrochen. Bisher habe ich die Vorschläge von Nobuo T noch nicht eingebaut, sehe aber auch (noch!) keinen Nachteil.
..
-
Erhard Henkes schrieb:
@abc.w: Danke für die Übersetzung von Intel nach AT&T und für das DJGPP / mingw makefile. Es sollte nicht von zu vielen Kleinigkeiten und/oder Geschmacksachen abhängen, ob jemand den Zugang zu OSDEV findet.
Bitte, aber ich glaube, ich habe da noch den einen oder anderen Fehler eingebaut und es wundert mich, dass es funktioniert:
print_string: movb $0x0E, %ah 1: lodsb # grab a byte from SI testb %al, %al # test AL jz 2b # if the result is zero, get out int $0x10 # otherwise, print out the character! jmp 1b 2: ret
Die Zeile jz 2b soll natürlich nicht 2 back sonder 2 forward heissen...
print_string: movb $0x0E, %ah 1: lodsb # grab a byte from SI testb %al, %al # test AL jz 2f # if the result is zero, get out int $0x10 # otherwise, print out the character! jmp 1b 2: ret
Entschuldigung... werde es oben gleich korrigieren...
-
Ich denke das nächste, was nun notwendig wird, ist eine vollständige Datei video.c - da gibt es ja nicht viel zu erklären - mit verbesserten Darstellungsmöglichkeiten, denn im jetzigen Zustand kann man das Programm nicht auf die Menschheit los lassen. In keyboard.c fehlt eigentlich auch noch die Abfrage auf weitere Kombinationen mit Sondertasten neben Shift, aber ich bin erstmal froh, dass es nun generell läuft. Mit dem Keyboard Handling stehe ich echt auf Kriegsfuß.
-
Naja, so ganz sinnvoll sieht mir deine fetchandsigsbums-Funktion noch nicht aus... Meine Vorschlaege (eigentlich waere das ja nur noch eine Sache?) noch nicht drin, dafuer die grosse Endlosschleife noch immer. :p
Mehr als einen Durchgang solltest du in dieser Funktion einfach nicht machen. Auch fuer erweiterte Codes, die aus mehreren Scancodes bestehen, wird jedes Mal ein IRQ ausgeloest.
Mal morgen nochmal drueber schauen...video.c ... Mein Vorschlag waere erstmal globale Variablen fuer die character attributes und die aktuelle Bildschirmposition, etc. festzulegen. Evtl. sogar in der BDA im entsprechenden Format, wie es das VGA-BIOS tut.
Dann erstmal grundlegende Funktionen zum Positionieren des Cursors, Ausgabe von chars und Strings, setzen der attributes, etc. implementieren.
Darauf kannst du dann vielleicht eine abgespeckte Version von printf aufbauen, die zumindest mit 0-terminierten Strings vernuenftig arbeiten kann und evtl. auch sowas wie %x, %d, %c und %s unterstuetzt.
-
Eine Design-Frage: Wie geht man mit den "Handlern" bezüglich IRQ am besten um?
Der nachstehende keyboard_handler(...) holt ein Zeichen in einen lokalen Puffer.
Wie geht man mit all diesen Informationen egal ob Tick-Info oder ein Zeichen von der Tastatur schnittstellenmäßig am besten um? Hier die zwei bisherigen Beispiele für IRQ0 und IRQ1:void timer_handler(struct regs* r) { ++timer_ticks; if (eticks) --eticks; }
void keyboard_handler(struct regs* r) { // k_printf("keyboard handler works!", 8, 0x2); unsigned char bufferKEY[10]; bufferKEY[0] = k_getch(); k_printf(bufferKEY, 10,0xA); // the ASCII character }
Die Ergebnisse sind in einem Fall timer_ticks und eticks, im anderen Fall bufferKEY[0]. Was macht man damit sinnvollerweise, um überall damit umgehen zu können? Gibt es diesbezüglich eine allgemeine Theorie?
-
video.c ... Mein Vorschlag waere erstmal globale Variablen fuer die character attributes und die aktuelle Bildschirmposition, etc. festzulegen. Evtl. sogar in der BDA im entsprechenden Format, wie es das VGA-BIOS tut.
Dann erstmal grundlegende Funktionen zum Positionieren des Cursors, Ausgabe von chars und Strings, setzen der attributes, etc. implementieren.
Darauf kannst du dann vielleicht eine abgespeckte Version von printf aufbauen, die zumindest mit 0-terminierten Strings vernuenftig arbeiten kann und evtl. auch sowas wie %x, %d, %c und %s unterstuetzt.Genau so habe ich mir das auch vorgestellt, ist ja auch das übliche Verfahren bei x*y Textausgabe. Das bisherige k_printf(...) war nur eine Quick&Dirty-Notlösung, um rasch vorwärts zu gelangen.
dafuer die grosse Endlosschleife noch immer.
Das ist ja keine "echte" Endlosschleife, da ich dort mit continue oder break in die jeweils richtige Richtung ein-/aussteigen kann. Habe bisher noch keine perfekte Lösung für die passende Kontrollstruktur gefunden, weil man die while-Schleife verschieden durchlaufen muss. Ich hatte erst while (loopflag) geschrieben und das flag entsprechend gesetzt, dann aber festgestellt, dass man das auch durch ein einfaches break und Tschüss ersetzen kann.
Meine Vorschlaege (eigentlich waere das ja nur noch eine Sache?) noch nicht drin
Ich denke noch darüber nach, habe aber bisher keinen Nachteil im bisherigen Ablauf erkannt, ist aber auch alles noch zu chaotisch auf dem Bildschirm. Ab und zu tauchen da merkwürdige Zeichen an unerwarteten Stellen auf.
Auf jeden Fall vielen Dank an alle, die mich hier unterstützen!
Dieses Tutorial ist ein lang gehegter Wunsch. Bisher hatte ich mich aber nicht an die Materie heran gewagt, bin ja kein Informatiker, sondern Autodidakt. Nun bin ich aber bereits soweit eingedrungen in das Thema, dass es kein Zurück mehr gibt, nur noch vorwärts.
-
@Nobuo T:
Noch zu den Themen: Port 0x61 Bit7, EOI und IF..
http://wiki.osdev.org/PS2_Keyboard
Nobuo T:
Kurz aus- und wieder einschalten ueber Port 61h, Bit7.
Ich gehe davon aus, dass für das MSB 0->1 u. 1->0 der korrekte Weg ist.
Wann muss man dieses ACK(nowledgement) abgeben?
..
Ich sehe allerdings noch keinen Effekt mit/ohne ACK?
Es heisst ja auch: "without waiting for another IRQ".
Wir reagieren doch jetzt immer auf einen IRQ1. Also brauchen wir das nun nicht?
Wir hätten es wohl eher beim Polling benötigt??? Da ist es mir aber nicht negativ aufgefallen.Das EOI wird in irq.c gesendet.
..
Da war doch noch die Rede von einem IF? Ist dies das IF bei der CPU im Flag-Register?
http://de.wikipedia.org/wiki/Statusregister#Interrupt-Enable-Flag
-
Erhard Henkes schrieb:
Eine Design-Frage: Wie geht man mit den "Handlern" bezüglich IRQ am besten um?
Der nachstehende keyboard_handler(...) holt ein Zeichen in einen lokalen Puffer.
Wie geht man mit all diesen Informationen egal ob Tick-Info oder ein Zeichen von der Tastatur schnittstellenmäßig am besten um? Hier die zwei bisherigen Beispiele für IRQ0 und IRQ1:void timer_handler(struct regs* r) { ++timer_ticks; if (eticks) --eticks; }
void keyboard_handler(struct regs* r) { // k_printf("keyboard handler works!", 8, 0x2); unsigned char bufferKEY[10]; bufferKEY[0] = k_getch(); k_printf(bufferKEY, 10,0xA); // the ASCII character }
Die Ergebnisse sind in einem Fall timer_ticks und eticks, im anderen Fall bufferKEY[0]. Was macht man damit sinnvollerweise, um überall damit umgehen zu können? Gibt es diesbezüglich eine allgemeine Theorie?
oft wird sowas objektorientiert gemacht (betriebssysteme schreien förmlich nach einem objektorientiertes design). für frei laufende countdown-timer machste dir z.b. ein paar funktionen:
// erzeugt einen neuen timer und meldet ihn beim OS an. gibt 0 zurück, wenn kein timer alloziert werden konnte timer_t *timer_create(void); // startet den timer, der ab jetzt vom OS von 'timeout' bis 0 runtergezählt wird void timer_start (timer_t *timer, unsigned long timeout); // prüft ob der timer abgelaufen ist, gibt 0 zurück, wenn der timer noch läuft, sonst 1 int timer_expired (timer *t); // beseitigt den timer (trägt ihn z.b. aus der liste des OS aus und gibt seinen speicher frei) void timer_free (timer_t *timer);
^^die hardware-isr schaut bei jedem tick in eine verkettete liste, ob timer drin sind, die sie runterzählen muss.
zu den I/O-daten: am besten du benutzt FIFO-buffer für sowas. die ISR (z.b. von der tastatur) trägt empfangene daten in den FIFO ein und die anwendung holt sie sich raus. ein tastatur-FIFO kann recht klein sein und darf ältere daten überschreiben, weil uralte tastendrücke ja nicht mehr interessieren. ein benutzer-prozess kann dann einfach zeichen aus dem FIFO holen, z.b. so:
// hole ein zeichen aus dem tastatur-buffer. wenn c -1 (oder EOF) ist, war der FIFO leer int c = getchar();
-
@+fricky: Danke für die Ratschläge, kommt in die Planungs-/TODO-Liste. Momentan fehlt dem OS noch ein solches C-Modul mit Strukturen wie Stack (LIFO), Pipe/Queue/Cache (FIFO), verketteter Liste usw. In C++ wäre dies wirklich leichter zu realisieren, muss mal in meinen alten C-Büchern schmökern.