TASM che affronta di uno

Sep 12 2020

Attualmente sto implementando Snake per l'università e per questo dobbiamo usare TASM.

I miei dati di gioco principali sono disposti in questo modo (usando la sintassi C):

struct GameLine {
    uint8_t direction_bits[10];  // 2 bits per entry, the first entry is invalid since valid x positions start at one
    uint8_t collision_bits[5];  // 1 bit per entry, the first entry is again invalid but has to stay zero
    uint8_t aux;  // padding such that GameLine is 16 bytes big, also used to store other information at times.
};

struct GameData {
    struct GameLine lines[23];
} PHYSICAL_GAME_DATA;

Il problema è che la scrittura dei bit di direzione per ogni frame sovrascrive i bit di collisione di lettura per le posizioni x grandi (38 è la posizione massima, ma accade prima). Dico "leggi i bit di collisione" perché non sono stato in grado di verificare dove physical_game_datarisiede effettivamente perché non so come istruire l'assembler ( tasm) e / o il linker ( tlink) e / o il debugger ( td) per mostrarmelo.

Le dichiarazioni nel mio codice sono:

physical_game_data   DB 368 DUP (0)
; ..., Some `EQU`s for `aux` data I'm using to store other information
game_data EQU (offset physical_game_data) - 16  ; Since 1 <= y <= 23, this allows addressing a line via `game_data + (y << 4)`

Le cose di movcui sono più preoccupato qui (ce ne sono alcune in più, ma queste sono le due che rendono visibile il bug) sono queste due:

; This one is for writing a new direction
mov     BYTE [ds:game_data + bx],   dh
; ...
; This one is for reading a collision bit to check if the player lost
mov     dl,     [ds:game_data + 10 + si]

Guardando quelli in tdtuttavia si ottiene questo:

mov [bx+05AF],dh
; ...
mov dl,[si+05B8]

La differenza tra 0x05AF e 0x05B8 tuttavia è 9, non 10. Al momento ho "risolto" il problema aggiungendo 11 nel codice sorgente, il che significa che il bug non si verifica, ma preferisco risolverlo correttamente.

Presumo che questo sia il mio fraintendimento su TASM o sull'assemblaggio x86 / x86-16, ma non so cosa sia esattamente questo malinteso.

Ecco un file completo che presenta questo problema:


    .model  tiny
    .286

.data
datastart:
physical_game_data  DB 368 DUP (0)
; ..., Some `EQU`s for `aux` data I'm using to store other information
game_data           EQU (offset physical_game_data) - 16  ; Since 1 <= y <= 23, this allows addressing a line via `game_data + (y << 4)`

.code

        ORG 100h
start:
        mov         ax,                         seg datastart
        mov         ds,                         ax

        ; This one is for writing a new direction
        mov         BYTE [ds:game_data + bx],   dh
        ; ...
        ; This one is for reading a collision bit to check if the player lost
        mov         dl,                         [ds:game_data + 10 + si]

        ; Exit
        mov         ax,                         4C00h
        int         21h
end start

Compilato utilizzando tasm MRE.ASM, tlink MRE.OBJe ha aperto con tdutilizzo td MRE.EXE, il codice decompilato si legge:

mov ax,48AF
mov ds,ax
mov [bx+0103],dh
mov dl,[si+010C]
mov ax,4C00
int 21

Dove, ancora una volta, 0x10C - 0x103 è 9.

Se è di interesse, sto eseguendo questo codice in Dosbox.

Grazie!

Risposte

5 RossRidge Sep 11 2020 at 23:34

Il tuo problema è la parola chiave BYTE. Nella modalità MASM la parola chiave BYTE restituisce la dimensione di un BYTE: 1. Ciò viene aggiunto all'espressione tra le parentesi quadre []poiché le parentesi quadre agiscono principalmente come un operatore di addizione nella modalità MASM. Dovresti BYTE PTR [ds:game_data + bx]invece scrivere , sebbene la tua prossima istruzione dimostri che puoi anche lasciarla fuori.