Kleines Spiel
-
Ein Spiel, das allein im Bootsektor läuft.
[BITS 16] mov ax, 0x07C0 ; ds:si to boot sector mov ds, ax mov ax, 0x13 ; mode 13h int 0x10 mov ax, 0xA000 ; es:di to video ram mov es, ax xor cx, cx ; standard position xor dx, dx ; standard direction kb: mov si, brush ; contains color codes add si, dx mov di, cx mov bx, 0x303 ; outer:inner loop counter draw: lodsb ; ds:si -> al, inc si mov [es:di], al inc di dec bl jnz short draw add di, 0x13D ; next line dec bh mov bl, 0x3 jnz short draw xor ah, ah ; wait for key event, scan:ascii -> ax int 0x16 cmp ah, 0x48 ; arrow up jz short up cmp ah, 0x4B ; arrow left jz short left cmp ah, 0x4D ; arrow right jz short right cmp ah, 0x50 ; arrow down jz short down sub si, 0x9 ; use same direction jmp short kb up: or dl, dl ; direction up? jz short m_up xor dl, dl ; set direction jmp short kb m_up: sub cx, 0x140 ; move up jmp short kb left: cmp dl, 0x9 ; direction left? jz short m_left mov dl, 0x9 ; set direction jmp short kb m_left: dec cx ; move left jmp short kb right: cmp dl, 0x12 jz short m_right mov dl, 0x12 jmp short kb m_right: inc cx jmp short kb down: cmp dl, 0x1B jz short m_down mov dl, 0x1B jmp short kb m_down: add cx, 0x140 jmp short kb brush db 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x0, 0x0 ; up db 0x0, 0x5, 0x0, 0x5, 0x0, 0x0, 0x0, 0x5, 0x0 ; left db 0x0, 0x5, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0 ; right db 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0 ; down times 510-($-$$) hlt db 0x55 db 0xAA
Kompiliert mit nasm, funktioniert zumindest in bochs und am Laptop. Man bewegt ein 0x05-farbiges Vehikel über den Bildschirm.^^
Weiteres wird noch ausgedacht.
-
Gehört das nicht eher ins Assembler-Forum?
-
Dieser Thread wurde von Moderator/in Erhard Henkes aus dem Forum Projekt: OS-Development in das Forum Assembler verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
was möchtest du uns damit sagen?
-
Ach nichts spezielles, ich dachte ich stell das mal rein, vielleicht findet jemand ineffektive Stellen oder so. Außerdem war ich stolz auf meine ersten Zeilen Assembler. Schaut mal in die C++-Foren, was da geposted wird.
Außerdem ist's ein Betriebssystem. Daher das entsprechende Forum.
-
Thuruk schrieb:
Außerdem ist's ein Betriebssystem.
-
Thuruk schrieb:
Ach nichts spezielles, ich dachte ich stell das mal rein, vielleicht findet jemand ineffektive Stellen oder so. Außerdem war ich stolz auf meine ersten Zeilen Assembler. Schaut mal in die C++-Foren, was da geposted wird.
Außerdem ist's ein Betriebssystem. Daher das entsprechende Forum.
Eigentlich ist es ja eher nur eine bootfähige Anwendung, da ja keine externen Anwendungen darüber zur Ausführung gebracht werden können.
Ineffektive Stellen habe ich nur bei den Sprungbefehlen finden können. Ich glaube auch für NASM braucht man ein "short" nur angeben, wenn wir nach vorne springen. Ich glaube sonst nimmt NASM immer automatisch die Short-Variante wenn möglich. Die Änderungen dafür wären also nur von rein kosmetischer Natur und würden den Opcode selber nicht ändern.
Dirk
-
Weiß jemand, warum das folgende Programm nicht funktioniert? Wollte den PIT nutzen, um Funktionen periodisch aufzurufen.
lt. http://www.lowlevel.eu/wiki/Programmable_Interval_Timer:
Standardmäßg ist der PIT darauf initialisiert, alle 54,9254 ms den IRQ 0 auszulösen (das entspricht einer Frequenz von ungefähr 18,2 Hz). Im Real Mode hat das BIOS für den IRQ 0 eine entsprechende ISR eingerichtet, die bei jedem Aufruf einen 16-Bit-Zähler an der Adresse 0000:046C erhöht.
[BITS 16] mov ax, 0x13 int 0x10 mov ax, 0xA000 mov es, ax xor ah, ah mov ds, ax mov ax, 0x46C mov si, ax draw: mov di, [ds:si] ; 0000:046C, sollte 18,2mal/s erhoeht werden mov al, 0x05 mov [es:di], al ; sollte langsam den Bildschirm ausmalen jmp draw times 510-($-$$) hlt db 0x55 db 0xAA
-
Bitte gewöhne Dir an, für ein neues Thema einen neuen Thread zu eröffnen.
Thuruk schrieb:
xor ah, ah mov ds, ax
Das ist gefährlich. Wenn AL aus irgendeinem Grund nicht Null ist, dann zeigt DS irgendwohin. Besser ist: 'xor ax,ax'.
draw: mov di, [ds:si] ; 0000:046C, sollte 18,2mal/s erhoeht werden mov al, 0x05 mov [es:di], al ; sollte langsam den Bildschirm ausmalen jmp draw
Trickreich, trickreich... Ist es aber wirklich das, was Du willst? Nun ja, ich vermute, dass Du den Videospeicher überforderst, wenn gigahertzmäßig ständig dieselbe Stelle beschreibst. Folgendes funktioniert bei mir in DosBox:
draw: mov di, [ds:si] ; neues DI holen cmp di, bx ; hat sich DI verändert je draw ; nein: nochmal mov bx, di ; ja: altes DI retten mov al, 5 mov [es:di], al ; sollte langsam den Bildschirm ausmalen jmp draw
EDIT: Dein ursprüngliches Programm funktioniert bei mir in DosBox und auch als Bootsektor von Floppy gebootet. Es kann sich also nur um ein Problem in Deinem Emulator handeln (welchen benutzt Du?).
viele grüße
ralph
-
Gehört ja noch zum Spiel, an dem ich arbeite.
rkhb schrieb:
Trickreich, trickreich... Ist es aber wirklich das, was Du willst? Nun ja, ich vermute, dass Du den Videospeicher überforderst, wenn gigahertzmäßig ständig dieselbe Stelle beschreibst.
Das hätte ich bedenken sollen, vielen Dank für den Hinweis.
rkhb schrieb:
EDIT: Dein ursprüngliches Programm funktioniert bei mir in DosBox und auch als Bootsektor von Floppy gebootet. Es kann sich also nur um ein Problem in Deinem Emulator handeln (welchen benutzt Du?).
Hab's nun in deiner Variante am Laptop ausprobiert, funktioniert, leider aber nicht in Bochs. Dort ist die Stelle im Arbeitsspeicher scheinbar konstant.
Verwendete Konfigurationsdatei:
romimage: file=$BXSHARE/BIOS-bochs-latest cpu: count=1, ips=10000000, reset_on_triple_fault=1 megs: 32 vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest vga: extension=vbe boot: floppy floppya: 1_44="C:\os\spiel.bin", status=inserted ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 boot: floppy floppy_bootsig_check: disabled=0 log: bochsout.txt panic: action=ask error: action=report info: action=report debug: action=ignore debugger_log: - parport1: enabled=1, file="parport.out" vga_update_interval: 300000 keyboard_serial_delay: 250 keyboard_paste_delay: 100000 mouse: enabled=0 private_colormap: enabled=0 keyboard_mapping: enabled=0, map= i440fxsupport: enabled=0
-
Gerade fertig programmiert. In Bochs ist die Verwendung des IRQ0 laut http://www.jamesmolloy.co.uk/tutorial_html/5.-IRQs%20and%20the%20PIT.html nicht möglich.
Note however that bochs does not accurately emulate the timer chip, so although your code will run at the correct speed on a real machine, it probably won't in bochs!
Am Laptop läuft's aber tadellos.
Der Timer sorgt dafür, dass max. alle 1/60s Bewegungen durchgeführt und der Grafikspeicher beschrieben werden, weitere Objekte könnten in der movement phase und draw phase verarbeitet werden, in der input phase weitere Aktionen, in der draw phase außerdem eine Kollisionsabfrage.
[BITS 16] mov ax, 0x13 ; mode 13h int 0x10 mov al, 110110b ; set timer out 0x43, al mov ax, 19886 ; app. 60Hz out 0x40, al xchg ah, al out 0x40, al ; =============================== TIMER =============================== ; ; === changing ax, dx ============================ do not change dx === ; main_loop: xor ax, ax ; ds:si=0000:046C mov ds, ax mov si, 0x46C cmp dx, [ds:si] ; counter increased? mov dx, [ds:si] ; save counter mov ax, 0x07C0 ; ds:si to boot sector mov ds, ax jz keyboard ; if counter was increased ; =============================== MOVEMENT PHASE ====================== ; ; === changing ax ===================================================== ; mov ax, 0x07C0 ; es:di to boot sector mov es, ax mov ax, [change] add [position], ax ; [es:position]+=[ds:change] xor ax, ax mov [change], ax ; [es:change]=0 ; =============================== DRAW PHASE ========================== ; ; === changing ax, cx ================================================= ; draw: mov ax, 0xA000 ; es:di to video ram mov es, ax mov di, [position] ; di=[ds:position] mov si, brush add si, [direction] ; si=brush+[ds:direction] mov cx, 0x303 ; outer:inner draw_loop counter draw_loop: lodsb ; al=[ds:si], inc si mov [es:di], al ; drawing pixel inc di dec cl jnz draw_loop add di, 0x13D ; next line dec ch mov cl, 0x3 jnz draw_loop ; =============================== INPUT PHASE ========================= ; ; === changing ax, cx ================================================= ; keyboard: mov ax, 0x07C0 ; es:di to boot sector mov es, ax sub si, brush+0x9 ; si=previously drawn direction mov cx, si in al, 0x60 ; al=scan code cmp al, 0x48 ; arrow up jz up cmp al, 0x4B ; arrow left jz left cmp al, 0x4D ; arrow right jz right cmp al, 0x50 ; arrow down jz down jmp short main_loop up: xor ch, ch ; set direction cmp ch, cl ; already drawn? jnz save_dir mov ax, 0xFEC0 ; set change jmp short save_dir_cha left: mov ch, 0x9 ; set direction cmp ch, cl ; already drawn? jnz save_dir mov ax, 0xFFFF ; set change jmp short save_dir_cha right: mov ch, 0x12 cmp ch, cl jnz save_dir mov ax, 0x1 jmp short save_dir_cha down: mov ch, 0x1B cmp ch, cl jnz save_dir mov ax, 0x140 save_dir_cha: mov [change], ax ; set change for next movement phase save_dir: mov [direction], ch ; set direction for next draw phase jmp word main_loop ; =============================== DATA ================================ ; ; === change, position and direction changed ========================== ; change db 0x0, 0x0 ; set at input phase, used & unset at movement phase position db 0x0, 0x0 ; set and used at movement phase direction db 0x0 ; 0, 9, 12h, 1Bh, set at input phase brush db 0x0, 0x5, 0x0, 0x5, 0x1, 0x5, 0x0, 0x0, 0x0 ; up db 0x0, 0x5, 0x0, 0x5, 0x1, 0x0, 0x0, 0x5, 0x0 ; left db 0x0, 0x5, 0x0, 0x0, 0x1, 0x5, 0x0, 0x5, 0x0 ; right db 0x0, 0x0, 0x0, 0x5, 0x1, 0x5, 0x0, 0x5, 0x0 ; down times 510-($-$$) hlt db 0x55 db 0xAA
Edit: kleiner Fehler behoben.