【发布时间】:2015-12-21 08:00:33
【问题描述】:
好吧,希望这是一个简单的问题:我需要访问一个数组以在 16 位 TASM 中实现双缓冲(我使用模式 13h)。但是:无论我使用“OFFSET”、“BYTE PTR [Array]”、“BYTE PTR Array”还是我已经尝试过的任何方法,程序都会读取/写入不正确的内存块,这部分是在实际启动之后数组。
这是我的(目前还没有真正优化且非常混乱)代码:
.MODEL MEDIUM
.STACK
.DATA
XPos DW 0
YPos DB 0
Color DB 0
BoxX1 DW 0
BoxY1 DB 0
BoxX2 DW 0
BoxY2 DB 0
VPage DB 64010 DUP(0) ;TODO: Size *might* be incorrect.
PageSeg DW 0
.CODE
SetVGA13 PROC
MOV AX, 0013h ;Screen mode 13.
INT 10h ;Set screen mode to AX.
MOV AX, 0A000h ;Screen segment.
MOV ES, AX ;You can't affect segment registers
RET
ENDP
;-------DrawPixel---------------
; WORD XPos = x
; WORD YPos = y
; BYTE Color = colour
;-------------------------------
DrawPixel PROC
XOR AH, AH
MOV AL, [YPos]
MOV DX, 320
MUL DX
ADD AX, [XPos]
MOV DI, AX
MOV AL, [Color]
MOV ES, [PageSeg]
;ADD ES, DI
MOV ES:[DI],AL
;MOV ES:[DI],AL
RET
ENDP
DrawBox PROC
MOV CL, [BoxY1]
YLoop:
MOV BL, CL
PUSH CX
MOV CX, [BoxX1]
XLoop:
MOV [XPos], CX
MOV [YPos], BL
MOV [Color],CL
CALL DrawPixel
INC CX
CMP CX, [BoxX2]
JNZ XLoop
POP CX
INC CL
CMP CL, [BoxY2]
JNZ YLoop
RET
ENDP
WaitFrame PROC
PUSH DX
; Port #03DA contains VGA status
MOV DX, 03DAh
IN AL, DX
WaitRetrace:
; Bit 3 will be on if we're in retrace
TEST AL, 08h
JNZ WaitRetrace
EndRefresh:
IN AL, DX
TEST AL, 08h
JZ EndRefresh
POP DX
RET
ENDP
RestoreVideo PROC
; Return to text mode
MOV AX, 03h
INT 10h
RET
ENDP
ClearScreen PROC
XOR CX, CX
;MOV ES, [PageSeg]
ClearLoop:
MOV DI, CX
;MOV ES, [PageSeg]
MOV BX, OFFSET VPage
ADD BX, CX
MOV AL, [BX];VPage[DI];ES:[DI]
MOV [Color],AL
MOV AX, 0A000h
MOV ES, AX
MOV AL, [Color]
MOV ES:[DI],AL
INC CX
CMP CX, 64000
JNZ ClearLoop
RET
ENDP
Main:
;INITIALISE
MOV BX, OFFSET VPage
MOV [PageSeg],BX
CALL SetVGA13
;CALL MakePalette
MOV [BoxX1],33
MOV [BoxY1],33
MOV [BoxX2],99
MOV [BoxY2],99
;LOOP
GameLoop:
;DRAW
;CALL DrawBox
CALL ClearScreen
;CALL WaitFrame
;INPUT
MOV DX, 60h
IN AL, DX
CMP AL, 75
JNZ NotLeft
SUB [BoxX1],1
SUB [BoxX2],1
NotLeft:
IN AL, DX
CMP AL, 77
JNZ NotRight
ADD [BoxX1],1
ADD [BoxX2],1
NotRight:
CMP AL, 1
JNZ GameLoop
;END PROGRAM
Error:
;CALL ClearScreen
CALL RestoreVideo
MOV AH, 4Ch
INT 21h
END Main
这段代码显示了一个彩虹色的盒子,你可以用左右箭头键移动它,
;INITIALISE
MOV BX, OFFSET VPage
MOV [PageSeg],BX
这是我获取缓冲区指针的可悲尝试,但没有返回正确的指针
对不起,我的问题没有完成,当我出于某种原因立即起床时,我意识到。
【问题讨论】:
-
我建议使用调试器(在您的情况下为 Turbo 调试器)单步执行代码以查看发生了什么。
-
您没有提及您认为是哪个内存地址或数组(甚至是哪个指令)有问题。
-
我已投票决定关闭这不是 Minimal, Complete, Verifiable example 。没有描述程序做什么、如何工作、预期什么以及发生什么。引用了访问
Array可能出现的问题,但代码中没有这样的变量,也没有表明发布者认为问题出在哪里(特定指令)。一些代码在游戏循环中被注释掉了,我认为这不是一个很好的例子。 -
ds未正确初始化。 -
@FrankKotler 同样,除了未设置 DS(默认为 PSP)之外,我注意到的是 ES 被设置为
VPage的offset,这是完全错误的。发帖者可能希望用类似这样的东西来初始化 DS、ES 和PageSeg,而不是MOV BX, @data,然后是MOV DS, BX,然后是MOV [PageSeg],BX。
标签: pointers assembly x86 tasm segment