簡體   English   中英

如何在 x86 中保留數組或字符串

[英]How to preserve an array or string in x86

我正在使用 tasm asm/dosbox 在 x86 中編寫游戲“15 益智游戲”。 我想“保存”或“保留”在我的數據段中聲明的名為“a”的數組,以便在使用 upArrow、downArrow 等交換字節后...然后按“n”新游戲,我可以將我的數組“a”設置回原來的 state,因為它在我的數據段中聲明。 這是我的代碼:

.MODEL TINY
.386

.DATA
PROMPT DB "Enter q to quit, arrow keys to move, n to restart (new game) HAPPY HOLIDAYS!! :)$"

;this is board preset A
a       DB 201,205,205,205,205,203,205,205,205,205,203,205,205,205,205,203,205,205,205,205,203,205,205,205,205,203,205,205,205,205,187,
    DB 186,255,48,50,255,186,255,48,49,255,186,255,48,51,255,186,255,48,52,255,186,255,48,53,255,186,255,48,54,255,186,
    DB 204,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,185,
    DB 186,255,48,55,255,186,255,48,56,255,186,255,48,57,255,186,255,49,48,255,186,255,49,49,255,186,255,49,50,255,186,
    DB 204,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,185, 
    DB 186,255,49,51,255,186,255,49,52,255,186,255,49,53,255,186,255,49,54,255,186,255,49,55,255,186,255,255,255,255,186,
    DB 204,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,185, 
    DB 186,255,49,56,255,186,255,49,57,255,186,255,50,48,255,186,255,50,49,255,186,255,50,50,255,186,255,50,51,255,186,
    DB 200,205,205,205,205,202,205,205,205,205,202,205,205,205,205,202,205,205,205,205,202,205,205,205,205,202,205,205,205,205,188,"$"


col DB 0
row DB 0
board DB 0

.CODE
org 100h
MAIN PROC

;initialize display step 0
MOV AH, 00h
MOV AL, 03h
INT 10h

MOV AX, 0B800h
MOV ES, AX
XOR di,di


;initialize configuration and dislay prompt step 1
newGame:
call initConfig

;display board step 2


;wait for key step 3
game:
;print board
call printBoard1

;get cursor x y
call SetCursor

MOV AH, 0
INT 16H

MOV BL, AL

;up arrow
CMP AH, 48h
jz upArrow

;down arrow
CMP AH, 50h
jz downArrow

;right arrow
CMP AH, 4dh
jz rightArrow

;left arrow
CMP AH, 4bh
jz leftArrow

;lowercase q
CMP AL, 71h
jz EXIT

;uppercase q
CMP AL, 51h
jz EXIT

;lowercase n
CMP AL, 6eh
jz newGame

;uppercase n
CMP AL, 4eh
jz newGame

jmp game

MAIN ENDP

EXIT:
MOV AH, 4CH                  ; return control to DOS
INT 21H

SetCursor:
mov dl, col
mov dh, row
mov bh, 0
mov ah, 02h
int 10h
ret

getStrlen:
lodsb
cmp al, 24h
je strlen_end
inc bx
jmp getStrlen
strlen_end:
ret

loadAndDisplayStr:
lodsb
stosw
dec cx
jne loadAndDisplayStr
ret

printBoard1:
MOV board, 1
xor dx,dx
xor ax,ax
mov cx, 9
myloop1:
push cx
lea si, a
add si, dx
mov cx, 31
mov di, ax
push ax
mov ah, 4
call loadAndDisplayStr
pop ax
add ax, 160
add dx, 32
pop cx
dec cx
jnz myloop1
ret

upArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
sub row, 2
mul row
add al, col
mov di, ax
mov ax, 32
add row, 2
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
sub row, 2
jmp game

downArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
add row, 2
mul row
add al, col
mov di, ax
mov ax, 32
sub row, 2
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
add row, 2
jmp game

leftArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
sub col, 5
mul row
add al, col
mov di, ax
mov ax, 32
add col, 5
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
sub col, 5
jmp game

rightArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
add col, 5
mul row
add al, col
mov di, ax
mov ax, 32
sub col, 5
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
add col, 5
jmp game

initConfig:
;put the cursor at 00
mov col, 27
mov row, 5

;gets strlen of prompt and stores it in BX
lea si, PROMPT
xor bx, bx
call getStrlen

;display prompt
lea si, PROMPT
mov cx, bx
mov ah, 2
mov di, 5a0h
call loadAndDisplayStr
ret

END MAIN

我認為有兩種方法可以做到這一點。 一種方法是創建一個空數組,每次用戶移動(上/下/左/右)時,我都可以將其推送到堆棧中,然后當用戶為新游戲點擊“n”時,我只是彈出該堆棧並反轉所有動作。

另一種選擇是創建2個相同的板(數組/字符串)'a'和'b',然后用戶將操縱板'a'直到他們決定為新游戲點擊'n',然后我會一些如何設置'a' = 'b'

沒有什么神奇的方法,你只需要像在 C 中一樣復制數組。 我建議擁有一份您保持干凈/未觸及的數據的主副本,永遠不要寫入它。

為工作游戲 state 分配未初始化的空間,例如在堆棧上或 BSS 1中。

在每場比賽開始時(包括第一場比賽),將預設的整個數組復制到當前比賽的暫存空間。 (例如,在設置 CX、SI 和 DI 之后使用rep movsbrep movsw和 DS 段 regs 已經是相等的段,因為。model tiny。即實現一個 memcpy,但你喜歡。)

所以你不需要寫兩次初始化數據或類似的東西,文件中只需要一個副本。

不,你不需要任何交換,只是一個塊副本。 通過在末尾放置 label 或將datasize = $ - a放在a的末尾之后,讓匯編器計算整個事物的大小,以獲取以字節為單位的大小。


腳注 1 :有關如何在.data? 段,以便您可以使用正常的標簽/符號語法。 gamestate datasize dup(?)一樣,其中datasize是一個=equ常量,您可以讓匯編器從預設的大小更早地進行計算。

我認為.data? 只是 DOS 加載您的.com文件的末尾之后的空間,您可以使用從那里到程序加載器放置堆棧的 64k 段末尾附近的空間。 (與現代操作系統下的 .bss 不同,一開始並沒有歸零。這很好,你想在閱讀/修改之前寫下你使用的空間。)


@DavidWohlferd 還建議您可以使用 DOS 文件打開/讀取系統調用從磁盤重新讀取部分可執行文件。 這可能是保存游戲機制的開始。 在最簡單的形式中,如果您的程序的前n個字節都是只讀的(代碼和常量數據),除了這個游戲狀態數組,您可以將原始.com文件的前n個字節讀取到ds:100h (或cs或es,在微型memory模型中都是一樣的)。 用自己覆蓋指令(比如對數據的jmp rel16 )很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM