我试图在8086程序集中移动一个6x6像素的对象,但没有运气。 我希望它每秒移动4个像素,但目前它根本没有移动。
如果有人可以帮助我,我会很高兴,因为这是我高中计算机学习决赛的一个重要项目,我一直到周末结束
这是代码本身
IDEAL
MODEL medium
DATASEG
STACK 100h
segment extra para public use16 ;Create Extra Segment that is 16 bits;
;(Removed the data segment for your sake, its very long pixel lists)
CODESEG
; -------------------------------
; change screen mode to text mode
; -------------------------------
proc DrawPix
ContLines:
mov cx, [LineLength] ; How many times should the "rep movsb" should iterate
push di ; Save in stack the calculated position indicating the begining of the current line
rep movsb ; copies bytes from si(image) to di (screen)
pop di ; di was changed during the movesb. I change it back to pint to the begin of the line
add di, ScreenWidth ; by adding ScreenWidth (320)' I am moving the di to point to the next line
dec [NumOfLines] ; Check if I wrote all the lines of the image
jnz ContLines ; IF there are still pixcells to print on the screen(image not ended), loop to next line
ret
endp
proc keycontrol
;check for arrow keys, and go to check arrow removed;
jmp Shoot
checkarrow:
removed, irrelevant (supposed to change direction of turret)
Exit:
ret
endp
proc Shoot
cmp [turretstate],1 ;turret facing up
je bulletup
cmp [turretstate],2;turret facing down
je bulletdown
cmp [turretstate],3;turret facing left
je bulletleft
cmp [turretstate],4;turret facing right
je bulletright
ret
bulletup:
not relevant for testing left movement
bulletdown:
not relevant for testing left movement
bulletright:
not relevant for testing left movement
bulletleft:
mov di,320*87+133
lea si, [bullet]
mov [LineLength],6
mov [numOFLines],6
call DrawPix
ret
endp
proc leftbull
pop dx
dec dx
mov di,320*84
add di,dx
lea si, [bullet]
mov [LineLength],6
mov [NumOfLines],6
call DrawPix
ret
endp
proc progbullets
mov dx,0
checkleft:
inc dx
cmp dx,136
je exit1
mov cx,87
mov ah,0Dh
int 10h
cmp al,4
jne checkleft
push dx
call leftbull
exit1:
ret
endp
;---------------------------------------------;
;---------------------------------------------;
start:
Main_Loop:
mov [sectimer], 0
mov ah,00H
int 1Ah
mov [sectimer],dx
call keycontrol
func_Loop:
call progbullets
mov ah,00H
int 1Ah
sub dx,18
cmp dx,[sectimer]
jge Main_Loop
;call moveGame
jmp func_Loop
; call the operating system to terminate this program
mov ah,1
int 21h
mov ax, 4C00H
int 21h
ends
end start
该程序有一个起始屏幕,可以移动炮塔,并放置“子弹”,但我无法让它们移动,它也有一些奇怪的像素。 拍摄过程是主要问题,它应该在x值上一个接一个(子弹保持在相同的y值),并检查像素是否为红色(子弹颜色),如果是这样的话它还剩下一个。
编辑:非常感谢您的帮助,我是新来的,真的需要它。我没有适合gui tasm的调试器,这是我正在使用的系统,所以我很难做到这一点 我删除了大部分不必要的东西,但不确定还有什么不必要,因为我不确定什么是不起作用的东西。我猜“射击”过程是最相关的。拍摄仅适用于左侧子弹,因为我想先测试它,但它不适用于此
答案 0 :(得分:2)
缩短代码的主要问题之一是:
push dx
call leftbull
...
proc leftbull
pop dx
dec dx
您错过了call
和ret
说明的实施细节。它们也使用“堆栈”存储区域,因此pop dx
不会在push dx
之前读取call
存储到堆栈中的值,而是“返回地址”,即地址call
指令后的下一条指令。
您可以使用您自己的子程序调用约定来修复这样的问题,您可以在寄存器中传递参数,例如在这种情况下只删除push dx
和pop dx
,因为您已经拥有所需的dx
中的值(但请验证是否也从其他地方调用了leftbull
,以修复该调用以将参数放入dx
)。
另外一点是,搜索现有子弹的像素数据有点天真和原始的方法。而是在数据段中为子弹位置保留一些空间(取决于您可以同时在屏幕上显示多少个子弹),并继续更新这些位置,这样您就不需要通过像素数据搜索当前位置。 / p>
另外,对于更复杂的游戏,您可以将一些精灵相互绘制,因此在这种情况下搜索像素数据会失败,因为精灵“在”下面是不可见的=未找到。但读取视频内存的速度也非常慢,因此扫描320像素的速度远远低于扫描数据段中的320字节。通过int 10h
服务读取像素值通常比直接从视频内存中读取它们要慢十倍,因此您当前的想法比使用子弹位置“变量”慢约200-1000倍,并通过这些更新子弹
重新考虑你的整个游戏原理图和主循环算法,或者尝试在纸上画一段时间,你真正需要存储什么,以保持完整的“世界状态”,让你从头开始重绘世界框架(有点跟随现代MVC SW架构模式),还有那些不同的上/下/左/右代码变体...尝试对其进行参数化,因此您可以使用单个通用例程处理所有情况,根据以下内容执行不同的操作特定子弹的参数。
我为一场代码高尔夫比赛做过一次2048字节长的DOS游戏,所以代码并不是最可读的,但你可能还是快速看一下,也许它会激发你一两件事(来源是包括在内,当时我正在使用TASM):http://www.pouet.net/prod.php?which=2692