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.


Anmelden zum Antworten