Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Assembly: [FASM] Taulukko

ErroR++ [17.11.2011 20:24:13]

#

Moi!

Nyt tuli vastaan pieni ongelma. Teen pientä merkkigrafiikkapeliä huvikseni assemblyllä, ja haluan kartan taulukkoon. Pitääkö siihen tehdä joku oma strukti, esim.

struct map
line1 db 25 dup(?)
line2 db 25 dup(?)
line3 db 25 dup(?)
;jne...
ends
;luodaan uusi instanssi kartasta:
map1 map '#### ####################','####@####################', '#########################'

Vai pitääkö vain lukea kartta tiedostosta ja tumpata se yhteen muuttujaan?

jalski [18.11.2011 20:46:20]

#

ErroR++ kirjoitti:

Vai pitääkö vain lukea kartta tiedostosta ja tumpata se yhteen muuttujaan?

Siis yksinkertaisimmillaan ohjelmoijan näkökulmasta tuollainen kartta on vain label ja peräkkäisiä tavuja.

Alla historian kätköistä kaivettu yksinkertainen esimerkki structien käytöstä. Tarvinnee dosboxin tai OS/2:sen, jos tuota haluaa nykypäivänä kokeilla ajaa.

;*************************************************************************
; Simppeli animaatio testi
;
; käännä FLAT muistimallille
;
; Ohjelman kääntämisen ja linkitsemisen voi suorittaa
; käyttämällä OpenWatcom C/C++/ASM OpenSource kääntäjää,
; joka on kopioitavissa netistä ILMAISEKSI.
;
; Tai kopioimalla CauseWay tiedostot
; netistä osoitteesta:
;	 http://www.devoresoftware.com/freesource/cwsrc.htm
;
; ja kääntämällä MASM yhteensopivalla assemblerilla
; kuten TASM ja OpenWatcom paketissa oleva
; Openwatcom Assembler (WASM). Linkitseminen
; hoituu CauseWay -paketissa olevalla WL32 linkkerillä.
;
; Eli esim.	wasm anim.asm	(watcom assemblerilla)
;		wl32 anim.obj /f
;
;************************************************************************
;
.386            ; Tässä järjestyksessä
.model small    ;  takaavat use32 segmentit
.stack 1024 	; Pitäisi riittää useimmille ..

include cw.inc  ; CauseWay API

;-------------------------------------------------------------------------

VGA_SEGMENT equ 0A0000h

SPRITE_WIDHT equ 24
SPRITE_HEIGHT equ 16

SCREEN_WIDHT    equ 320
SCREEN_HEIGHT   equ 200

LEFT    equ 0
RIGHT   equ SCREEN_WIDHT-SPRITE_WIDHT
TOP     equ 0
BOTTOM  equ SCREEN_HEIGHT-SPRITE_HEIGHT

sprite_struc    struc
	x       dw      ?
	y       dw      ?
	deltax  dw      ?
	deltay  dw      ?
sprite_struc    ends

;--------------------------------------------------------------------------------

.data

SpriteList      label sprite_struc
sprite_struc <160,110,1,1>
sprite_struc <260,100,-1,1>
sprite_struc <60,50,1,-1>
sprite_struc <260,150,1,1>
sprite_struc <220,70,-1,1>
sprite_struc <200,110,1,-1>
sprite_struc <250,40,1,-1>
sprite_struc <140,30,-1,1>
sprite_struc <30,10,1,-1>
sprite_struc <40,90,-1,-1>
SpriteListEnd   label sprite_struc

align 4
ScreenBuffer dd ?       ;Osoitin näyttöpuskuriin

Mem_message     db 13,10,"Ei tarpeeksi muistia.",13,10,"$"
Exit_message    db 13,10,"Valmista.",13,10,"$"

;----------------------------------------------------------------------------------
;
.code

Main:
	; Osoita dataan
	mov ax,DGROUP
	mov ds,ax

	; Lukitse ohjelman muisti
	mov esi,es:[EPSP_MemBase]
	mov ecx,es:[EPSP_MemSize]
	sys LockMem32
	mov edx,offset Mem_message
	jc  Exit

	; Setup segment registers
	mov ax,ds
	mov es,ax
	mov fs,ax
	mov gs,ax

	; Varaa muistia näyttöpuskurille
	mov ecx,SCREEN_WIDHT*SCREEN_HEIGHT
	call Malloc
	mov edx, offset Mem_message
	jc  Exit
	mov [ScreenBuffer],esi

	; Aseta näyttötila
	mov eax,13h
	int 10h

	; Täytä näyttöpuskuri 0-värillä
	mov edi,esi
	mov ecx,(SCREEN_WIDHT*SCREEN_HEIGHT)/4
	mov eax,0
	rep stosd

@@AnimationLoop:
	call Move
	call Draw

	; Näppäimen painallus lopettaa
	mov ah,1
	int 16h                     ;onko näppäintä painettu ?
	jz  @@AnimationLoop         ;ei -aloita alusta

	sub ah,ah
	int 16h             ;kyllä, olemme valmiit
	; Tekstitila
	mov eax,3
	int 10h

	; Vapauta näyttöpuskurille varattu muisti
	mov esi,[ScreenBuffer]
	call Free

	mov edx,offset Exit_message

;-----------------------------------------------------------------------------------
;
; Tulostaa viestin ja lopettaa ohjelman
;
Exit:
	mov ah,09h
	int 21h

	mov ax,4c00h
	int 21h

;------------------------------------------------------------------------------------
;
;Varaa muistia.
;
;Syöttöparametrit:
;
;ECX    - tarvittava tavumäärä.
;
;Palauttaa:
;
;Carry asettuu, kun virhe muuten ..
;
;ESI    - lineaari muistiosoite
;
Malloc:
	push eax
	push ecx
	add ecx,4           ;Tee tilaa puskurin pituudelle.
	sys GetMemLinear32  ;Yritä varata muistia.
	jc  @@malloc_2
	sys LockMem32       ;Yritä lukita varattu muisti.
	jnc @@malloc_1
	sys RelMemLinear32  ;Jos lukitus ei onnistu, vapauta varattu muisti.
	stc
	jmp @@malloc_2
@@malloc_1:
	mov [esi],ecx       ;Tallenna varatun muistin määrä
	add esi,4           ; FREEtä varten.
	clc                     ;Varmista, että palautetaan onnistunut status.
@@malloc_2:
	pop ecx
	pop eax
	ret

;-------------------------------------------------------------------------------
;
;Vapauttaa MALLOCilla varatun muistin.
;
;Syöttöparametrit:
;
;ESI    - vapautettavan muistin lineaari osoite.
;
Free:
	push eax
	push esi
	push ecx
	sub esi,4           ;Haetaan varatun ..
	mov ecx,[esi]       ; muistin määrä.
	sys UnLockMem32     ;Poista lukitus.
	pop ecx
	sys RelMemLinear32  ;Vapauta muisti.
	pop esi
	pop eax
	ret

;--------------------------------------------------------------------------------
;
; Kuvatieto käännettynä suoraan kuvanpiirtorutiiniiksi
;
; Käännetyn spriten etuna on kaikkien vertailujen ja
; hyppyjen eliminointi. Haittana on, että spriten pitää
; pysyä kokonaan näytön rajoissa.
;
; Syöttöparametrit:
;
;       EAX - näyttöpuskurin osoite
;       EBX - y-koordinaatti
;       EDX - x-koordinaatti
;
Sprite:
	;Laskee näyttöosoitteen
	; vastaa seuraavaa: (320 * y) + x
	mov ecx,ebx
	shl ebx,08h
	shl ecx,06h
	add eax,ebx
	add eax,ecx
	add eax,edx

	; Piirtää kuvatiedon
	mov dword ptr [eax+0146h],010101010h
	mov dword ptr [eax+014Ah],010101010h
	mov dword ptr [eax+014Eh],010101010h
	mov byte  ptr [eax+0152h],010h
	mov dword ptr [eax+0284h],0E101010h
	mov dword ptr [eax+0288h],0E0E0E0Eh
	mov dword ptr [eax+028Ch],0E0E0E0Eh
	mov dword ptr [eax+0290h],010100E0Eh
	mov byte  ptr [eax+0294h],010h
	mov dword ptr [eax+03C3h],0E0E1010h
	mov dword ptr [eax+03C7h],0E0E100Eh
	mov dword ptr [eax+03CBh],0E0E0E0Eh
	mov dword ptr [eax+03CFh],0E0E0E10h
	mov word  ptr [eax+03D3h],0100Eh
	mov byte  ptr [eax+03D5h],010h
	mov dword ptr [eax+0501h],00E101010h
	mov dword ptr [eax+0505h],010100E0Eh
	mov dword ptr [eax+0509h],0E0E0E10h
	mov dword ptr [eax+050Dh],01010100Eh
	mov dword ptr [eax+0511h],0E0E0E0Eh
	mov word  ptr [eax+0515h],01010h
	mov dword ptr [eax+0641h],0E0E0E10h
	mov dword ptr [eax+0645h],010100E0Eh
	mov dword ptr [eax+0649h],0E0E0E10h
	mov dword ptr [eax+064Dh],01010100Eh
	mov dword ptr [eax+0651h],0E0E0E0Eh
	mov word  ptr [eax+0655h],0100Eh
	mov dword ptr [eax+0781h],0E0E0E10h
	mov dword ptr [eax+0785h],0100E0E0Eh
	mov dword ptr [eax+0789h],0E0E0E0Eh
	mov dword ptr [eax+078Dh],0E100E0Eh
	mov dword ptr [eax+0791h],0E0E0E0Eh
	mov word  ptr [eax+0795h],0100Eh
	mov dword ptr [eax+08C1h],0E0E0E10h
	mov dword ptr [eax+08C5h],0E0E0E0Eh
	mov dword ptr [eax+08C9h],0E0E0E0Eh
	mov dword ptr [eax+08CDh],0E0E0E0Eh
	mov dword ptr [eax+08D1h],0E0E0E0Eh
	mov word  ptr [eax+08D5h],0100Eh
	mov dword ptr [eax+0A01h],0E0E0E10h
	mov dword ptr [eax+0A05h],0E0E0E0Eh
	mov dword ptr [eax+0A09h],0E0E0E0Eh
	mov dword ptr [eax+0A0Dh],0E0E0E0Eh
	mov dword ptr [eax+0A11h],0E0E0E0Eh
	mov word  ptr [eax+0A15h],0100Eh
	mov dword ptr [eax+0B41h],0E0E0E10h
	mov dword ptr [eax+0B45h],0E0E0E0Eh
	mov dword ptr [eax+0B49h],0E0E0E0Eh
	mov dword ptr [eax+0B4Dh],0E0E0E0Eh
	mov dword ptr [eax+0B51h],0E0E0E0Eh
	mov word  ptr [eax+0B55h],0100Eh
	mov dword ptr [eax+0C81h],0E0E0E10h
	mov dword ptr [eax+0C85h],0E0E0E10h
	mov dword ptr [eax+0C89h],0E0E0E0Eh
	mov dword ptr [eax+0C8Dh],0E0E0E0Eh
	mov dword ptr [eax+0C91h],0E0E100Eh
	mov word  ptr [eax+0C95h],0100Eh
	mov dword ptr [eax+0DC1h],0E0E0E10h
	mov dword ptr [eax+0DC5h],0E0E100Eh
	mov dword ptr [eax+0DC9h],0E0E0E0Eh
	mov dword ptr [eax+0DCDh],0E0E0E0Eh
	mov dword ptr [eax+0DD1h],0E0E0E10h
	mov word  ptr [eax+0DD5h],0100Eh
	mov dword ptr [eax+0F01h],00E101010h
	mov dword ptr [eax+0F05h],010100E0Eh
	mov dword ptr [eax+0F09h],010101010h
	mov dword ptr [eax+0F0Dh],010101010h
	mov dword ptr [eax+0F11h],0100E0E0Eh
	mov word  ptr [eax+0F15h],01010h
	mov dword ptr [eax+01043h],0E0E1010h
	mov dword ptr [eax+01047h],0E0E0E0Eh
	mov dword ptr [eax+0104Bh],0E0E0E0Eh
	mov dword ptr [eax+0104Fh],0E0E0E0Eh
	mov word  ptr [eax+01053h],01010h
	mov dword ptr [eax+01184h],010101010h
	mov dword ptr [eax+01188h],010101010h
	mov dword ptr [eax+0118Ch],010101010h
	mov dword ptr [eax+01190h],010101010h
	ret

;--------------------------------------------------------------------------------------
;
; Liikuttaa spritejä
;
Move:
	mov ebx,offset SpriteList   ;osoita sprite listaan

@@CheckXLeftLimit:
	mov cx,[ebx+x]
	cmp cx,LEFT                ;vasen reuna ?
	ja  @@CheckXRightLimit     ;ei -tarkasta oikea reuna
	neg [ebx+deltax]           ;kyllä -käännä X suunta

@@CheckXRightLimit:
	cmp cx,RIGHT               ;oikea reuna ?
	jb  @@MoveX                ;ei -aika liikuttaa
	neg [ebx+deltax]           ;kyllä -käännä X suunta

@@MoveX:
	add cx,[ebx+deltax]         ;lisää X koordinaattiin
	mov [ebx+X],cx              ;talteen

@@CheckYTopLimit:
	mov dx,[ebx+y]
	cmp dx,TOP                 ;yläreuna ?
	ja  @@CheckYBottomLimit    ;ei -tarkasta alareuna
	neg [ebx+deltay]           ;kyllä -käännä Y suunta

@@CheckYBottomLimit:
	cmp  dx,BOTTOM            ;alareuna ?
	jb @@MoveY                ;ei -aika liikuttaa
	neg [ebx+deltay]          ;kyllä -käännä Y suunta

@@MoveY:
	add dx,[ebx+deltay]         ;lisää Y koordinaattiin
	mov [ebx+y],dx              ;talteen

@@DoNextObject:
	add ebx, size sprite_struc           ;osoita seuraavaan objektiin
	cmp ebx, offset SpriteListEnd       ;ollaanko listan lopussa ?
	jb @@CheckXLeftLimit               ;ei -seuraava objekti

	ret

;------------------------------------------------------------------------------------
;
; Piirtää spritet näyttöpuskuriin
;
Draw:
	mov     esi,offset SpriteList
@@DrawLoop:
	mov eax,[ScreenBuffer]
	movzx ebx,[esi+y]
	movzx edx,[esi+x]
	call Sprite
	add esi,size sprite_struc           ;osoita seuraavaan objektiin
	cmp esi, offset SpriteListEnd       ;ollaanko listan lopussa ?
	jb @@DrawLoop                      ;ei -seuraava objekti

; Kopioi näyttöpuskurin sisällön näytölle
@@BufferToScreen:
	mov esi,[ScreenBuffer]
	mov edi,VGA_SEGMENT
	mov ecx,(SCREEN_WIDHT*SCREEN_HEIGHT)/4

	mov dx,3dah                     ;VGA portti ja indeksi (Input Status Register)
@@Retrace:
	in al,dx                        ;lue VGA portti
	and al,8                        ;selvitä tahdistuksen tila
	jz @@Retrace                    ;odota näytön tahdistusta

	cld
	rep movsd                       ;kopioi 32-bittiä kerrallaan

	ret
;------------------------------------------------------------------------------------
	end     Main

Deffi [18.11.2011 22:32:26]

#

format PE GUI 4.0
include 'win32ax.inc'

.code
start: invoke MessageBox, 0, juttu, 0, 0
       invoke ExitProcess, 0
.end start

.data
juttu db 'abc'
      db 'def'
      db 0

Näyttää tekstin 'abcdef'.

ErroR++ [19.11.2011 21:12:53]

#

Entä sitten törmäystesti?
Eikö kartan pitäisi olla taulukossa ja lisäksi: kartta ladataan tiedostosta (vähän WinAPI -pelleilyä ja CloseHandleja niin eiköhän sen kartan voi sieltä kiintolevyltä ladata).

Grez [19.11.2011 23:36:29]

#

Kaikkihan on "jonossa" siellä muistissa. Jos ajattelet esim. 2-ulotteista taulukkoa, niin tämähän on (korkeamman tason) kielien tarjoama abstraktio. Assemblyssä voit toteuttaa sen millä tavalla haluat.

Deffi [21.11.2011 18:21:08]

#

; juttu[y][x] = juttu[y*rivin_leveys + x]
;
; tulo tallenetaan eaxin ja edxin muodostamaan 64-bittiseen
; muuttujaan (vähemmän merkitsevä osa eaxissa riittää)
mov eax, 1      ; rivi 1
mov ecx, 3      ; yhden rivin pituus
mul ecx         ; kertolasku
mov al, [juttu+eax+2]
; nyt al = 0x66 = 'f'

juttu db 'abc'
      db 'def'
      db 0

Jos kerrotaan kahden potenssilla, niin kertolaskun voi korvata shl-käskyllä. Kertomisen luvulla joka on muotoa 2^n + 1 (missä 0 <= n <= 3) pystyy kikkailemaan lea-käskyllä (esim. lea eax, [eax*8+eax]).

ErroR++ [22.11.2011 17:51:23]

#

Nyt älysin! Kiitos avusta!

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta