【问题标题】:i don't know why the score system doesn't work我不知道为什么评分系统不起作用
【发布时间】:2017-05-22 16:27:36
【问题描述】:

我正在使用带有 tasm 的 dosbox。

这是用汇编程序编写的代码的主要部分。

IDEAL
MODEL small  
STACK 100h
P186 

include 'GL1.asm'  

DATASEG

ballX DW 160
ballY DW 100
ballColor DB 4
BALL_SIZE  EQU  20
ballDeltaX DW ?
ballDeltaY DW ?
scorr db 0

randChangeCounter DW ?

CODESEG

start:
mov ax, @data
mov ds, ax
mov ax, 13h
int 10h
mov al,[ballColor]
call glBall 
mov CX,60
mov [ballDeltaX],-2
mov [ballDeltaY],-1
mov cx,300 
call SetCursor
Gameloop:
mov BH ,00h
call TickDelay

call mouse 

call Score

cmp [scorr] , 20
je exit
call randChange


call changeOnborder
call renderBall

call mouse 
call Score
cmp [scorr] , 20
je exit


jmp  Gameloop
exit:

mov ah, 0
mov al, 2
int 10h

mov ax, 4c00h
int 21h

proc renderBall
PUSHA

xor al,al  ; balck 
call glBall 

mov cx,[ballDeltaX]
add [ballX],cx
mov cx,[ballDeltaY]
add [ballY],cx

mov al,[ballColor]
call glBall 
POPA    
ret
endp renderBall

proc waitKey
PUSHA
mov ah,00h
int 16h 
POPA
ret
endp waitKey    

proc glBall 
PUSHA 
mov cx,[ballX]
mov dx,[ballY]
mov ah,BALL_SIZE
mov bl,BALL_SIZE

call glBox  
POPA
ret 
endp glBall

proc glBox 
PUSHA 
@@ONE_LINE  :
call glVLine  
inc dx
dec bl
jnz @@ONE_LINE
POPA
ret 
endp

proc glVLine 
PUSHA 
mov bl,ah 
mov bh,0
mov ah,0ch
@@ONE_PIXEL :
int 10h
inc cx
dec bl
jnz @@ONE_PIXEL
POPA
ret 
endp

proc randChange
push ax
inc [randChangeCounter]
cmp [randChangeCounter],20
jne @@skip
    mov [randChangeCounter],0

    mov ax,13 ; +-6
    call rand_max
    sub ax,6 
    mov [ballDeltaX],ax

    mov ax,13 ; +-4
    call rand_max
    sub ax,6 
    mov [ballDeltaY],ax

    mov ax,6 
    call rand_max
    add ax,2 
    mov [ballColor],al

@@skip:
pop ax
ret
endp randChange
proc SetCursor

mov ax, 0h
int 33h
mov ax, 1h
int 33h
mov ax, 3h
int 33h
ret
endp SetCursor
proc mouse
mov ax, 3h
int 33h
ret
endp mouse
proc Score

mov   ax,3h
int 33h
cmp  bl,1
je   Check_X1_Cords
ret
Check_X1_Cords:
cmp cx, [ballX]
jg Check_X2_Cords
ret
Check_X2_Cords:
cmp cx,[ballX+20]
jl Check_Y1_Cords
ret
Check_Y1_Cords:
cmp dx, [ballY]
jg ScoreLabel
ret
Check_Y2_Cords:
cmp dx, [ballY+20]
jl ScoreLabel
ret
ScoreLabel:
inc [scorr]
ret 
endp Score

proc changeOnborder
push ax

mov ax,[ballX]
add ax,[ballDeltaX] 
cmp ax,320-BALL_SIZE  
jg X_FIX
cmp ax,0
jge X_OK
X_FIX:  
mov [ballColor],1
neg [ballDeltaX] 
X_OK:

mov ax,[ballY]
add ax,[ballDeltaY] 
cmp ax,200- BALL_SIZE
jg Y_FIX
cmp ax,0
jge Y_OK
Y_FIX:  
mov [ballColor],1
neg [ballDeltaY] 
Y_OK:

pop ax
ret
endp changeOnborder

END start

这是 GL1.asm

 RANDPRIME    equ    401

 segment    biosdata    at 40h
 org    6ch
timer      dw    ?    ; clock ticks
ends

DATASEG
lastrand   dw    0


FastCounter  DW 0 ; 
SlowCounter  DW 0 ; 

CODESEG

;
; timeticks - get time ticks from bios data segment.
;
; Register Arguments:
;    None.
;
; Returns: 
;    ax - current ticks
;

proc    timeticks
push   es

mov    ax, biosdata
mov    es, ax
assume es:biosdata
mov    ax, [timer]
assume es:nothing
pop    es
ret
endp

;
; random - pseudo generate random number
;
; Register Arguments:
;    None.
;
; Returns:
;    ax - random number.
;
codeseg
proc    random
push   dx
push   bx
mov    bx, [lastrand]
mov    ax, bx
mov    dx, RANDPRIME
mul    dx
mov    dx, ax
call   timeticks
xor    ax, dx
xchg   dh, dl
xor    ax, dx
xchg   bh, bl
xor    ax, bx
mov    [lastrand], ax
pop    bx
pop    dx
ret
endp

proc    rand_max
push   dx
push   bx
mov bx,ax ; store max
call random ; -> ax
xor dx,dx
div bx
mov ax,dx   ; the reminder [0..max]

pop    bx
pop    dx
ret
endp rand_max
 ;===================== Delay ===================== 
Proc delay

push ax
push cx
push dx
push es

mov dx,0 
mov cx , 55
div cx  

mov cx, ax  
cmp cx,0
je Finish
DelayLoop:

call timeticks
mov dx,ax   
Tick:  
call timeticks
cmp dx,ax   
je Tick

loop DelayLoop
Finish: 

pop es 
pop dx
pop cx
pop ax
ret 
endp Delay  

proc  TickDelay
pusha

mov cx, 4 
each_sync:
  call wait_for_vsync
loop each_sync

popa
ret 
endp TickDelay

proc wait_for_vsync
pusha

mov dx, 03dah
@@previous_not_ended:
in   al, dx
test al, 08h
jnz  @@previous_not_ended

@@next_not_started:
in   al, dx
test al, 08h
jz  @@next_not_started

@@exit:
popa
ret
endp

我不知道该怎么办我认为问题出在 GL1 但我不确定。

任何根据问题或代码风格的帮助都会非常感激。

非常感谢。

【问题讨论】:

  • 你希望你的代码做什么?代码做了什么?请提供此信息。

标签: assembly x86-16 dos tasm


【解决方案1】:

快速浏览一下就发现了以下内容:

您的 timeticks 程序根本不读取 BIOS 计时器!
您已经为ES 段寄存器设置了所有内容,但mov ax, [timer] 指令完全依赖于DS 段寄存器。

这会破坏您的 rand_maxdelay 程序。
难怪它不起作用

换句话说,下面的代码变成了一个无限循环(因为timeticks很可能总是返回相同的值!):

    call  timeticks
    mov   dx, ax   
Tick:  
    call  timeticks
    cmp   dx, ax   
    je    Tick

【讨论】:

    【解决方案2】:

    很难说,“不起作用”是什么意思,以及您的代码应该做什么,但我会尝试猜测,以下部分没有按照预期进行(也许,您没有发表任何评论)。

        ...
        ; cx = 0..639 mouse.x position
    Check_X1_Cords:
        cmp cx, [ballX]
        jg Check_X2_Cords
        ret
    Check_X2_Cords:
        cmp cx,[ballX+20]
        jl Check_Y1_Cords
        ret
        ...
    

    问题是,ballX 符号是DW(两个字节)保留空间的内存地址。例如地址 0x1234。并且地址 0x1234 的内存包含例如两个字节:0x88 0x01 (0x0188 = 392)。假设鼠标位于 x 位置 550。

    然后第一个cmp 会将cx (550) 与地址0x1234 (0x0188 = 392) 的值进行比较,然后将jg 跳转到Check_X2_Cords

    第二个cmp 将比较cx (550) 与地址0x1234+20 = 0x1248 的值,这是内存中的任何值,但很可能不是有用的东西(可能为零,因为它看起来超出了数据段中的其他变量)。

    您可能确实想将第二个测试编写为:

        ...
    Check_X2_Cords:
        add cx,20
        cmp cx,[ballX]
        jl Check_Y1_Cords
        ...
    

    cmp cx,[ballX+20] 不会给内存中的值加 20,但它会给ballX 加 20,这是符号标签(内存中的地址),而不是值/变量。

    虽然一些汇编程序 (MASM) 支持像 mov ax,ballX 这样的语法,这使得它看起来ballX 变量(就像在高级语言中一样),它是 IMO只是混淆谬误,因为该指令的真实性质是mov ax,[offset_of_some_address],而ballX 是地址,而不是值。

    可能还有其他错误,我没有进行完整的代码审查,只是在我看到的第一个可疑的东西上停下来(大约 10 秒)。


    另一个快速捕获,在random 中,您正在使用一些时间数据来生成每个随机数?不要那样做,这也是错误的。仅使用时间刻度来计算一些初始“种子”值,之后随机生成器将工作。每次调用都将时间数据混合到其中实际上会使其非随机。你的RANDPRIME 太小了,但只是谷歌一些非常简单和快速(出于安全目的还不够好,但对于游戏来说它会做得很好)RNGR 算法,经典的算法几乎无处不在。

    【讨论】:

      猜你喜欢
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      • 2022-10-30
      • 2016-08-25
      • 2013-11-27
      • 1970-01-01
      • 2020-02-05
      • 1970-01-01
      相关资源
      最近更新 更多