我不知道分数系统为什么不起作用

时间:2017-05-22 16:27:37

标签: assembly x86-16 dos tasm

我正在使用带有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中,但我不确定。

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

提前多多感谢。

2 个答案:

答案 0 :(得分:1)

快速浏览显示以下内容:

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

这会破坏 rand_max 延迟程序。
难怪它不起作用

换句话说,以下内容变为无限循环(因为 timeticks 最有可能总是返回相同的值!):

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

答案 1 :(得分:0)

很难说,什么“不起作用”的意思,以及你的代码应该做什么,但我会试着猜测,以下部分没有做到预期的事情(也许,你没有评论任何事情)。

    ...
    ; 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算法,经典的算法肯定几乎无处不在。< / p>