Funzioni

Finora abbiamo scritto un solo “flusso” di codice, ma possiamo già individuare alcuni frammenti che sembrano ridondanti. Usiamo le funzioni per “sfoltire” il codice!

Per esempio, in tre punti stiamo copiando pezzi di memoria. Scriviamo una funzione sotto la jp Main e chiamiamola Memcpy, come l’analoga funzione C:

; Copy bytes from one area to another.
; @param de: Source
; @param hl: Destination
; @param bc: Length
Memcopy:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, Memcopy
	ret

La nuova istruzione ret' dovrebbe catturare immediatamente l'attenzione. È, senza sorpresa, quella che fa sì che l'esecuzione *ritorni* al punto in cui la funzione è stata *chiamata*. È importante notare che molti linguaggi prevedono una "fine" precisa per una funzione: in C o Rust, è la parentesi graffa di chiusura }; in Pascal o Lua, la parola chiave end, e così via; la funzione ritorna implicitamente quando l'esecuzione raggiunge la sua fine. Tuttavia, **non è così in assembly**, quindi bisogna ricordarsi di aggiungere un'istruzione ret` alla fine della funzione per ritornare da essa! Altrimenti, i risultati sono imprevedibili.

Notate il commento sopra la funzione, che spiega quali registri prende in ingresso. Questo commento è importante per sapere come interfacciarsi con la funzione; l’assembly non ha parametri formali, quindi i commenti che li spiegano sono ancora più importanti che in altri linguaggi. Ne vedremo altri man mano che procediamo.

Ci sono tre punti nel codice di inizializzazione in cui possiamo usare la funzione Memcpy. Trovate ognuno di questi cicli di copia e sostituiteli con una chiamata a Memcpy; per questo, utilizziamo l’istruzione call. I registri servono come parametri alla funzione, quindi li lasceremo così come sono.

Prima diDopo
	; Copy the tile data
	ld de, Tiles
	ld hl, $9000
	ld bc, TilesEnd - Tiles
CopyTiles:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, CopyTiles
	; Copy the tile data
	ld de, Tiles
	ld hl, $9000
	ld bc, TilesEnd - Tiles
	call Memcopy
	; Copy the tilemap
	ld de, Tilemap
	ld hl, $9800
	ld bc, TilemapEnd - Tilemap
CopyTilemap:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, CopyTilemap
	; Copy the tilemap
	ld de, Tilemap
	ld hl, $9800
	ld bc, TilemapEnd - Tilemap
	call Memcopy
	; Copy the paddle tile
	ld de, Paddle
	ld hl, $8000
	ld bc, PaddleEnd - Paddle
CopyPaddle:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, CopyPaddle
	; Copy the paddle tile
	ld de, Paddle
	ld hl, $8000
	ld bc, PaddleEnd - Paddle
	call Memcopy

Nel prossimo capitolo, scriveremo un’altra funzione, questa volta per leggere gli input del giocatore.