注册 登录
编程论坛 汇编论坛

为什么程序跳转后有条语句不执行?

paul_wing 发布于 2012-05-14 01:07, 1036 次点击
程序代码:

DATA      SEGMENT
INFO1     DB 0DH,0AH,'welcome to this programe!$'
INFO2     DB 0DH,0AH,'please enjoy the music!$'  
INFO6     DB 0DH,0AH,'music was stopped!$'
MUSLIST   DB 0DH,0AH,'press any key to stop the music!'
          db 0dh,0ah,'$'
;******************************************音乐 两只老虎
MUS_FREG3 DW 262,294,330,262
          DW 262,294,330,262
          DW 330,349,392
          DW 330,349,392
          DW 392,440,392,349,330,262
          DW 392,440,392,349,330,262
          DW 294,196,262
          DW 294,196,262,-1         
MUS_TIME3 DW 50,50,50,50
          DW 50,50,50,50
          DW 50,50,100
          DW 50,50,100
          DW 25,25,25,25,50,50
          DW 25,25,25,25,50,50
          DW 50,50,100
          DW 50,50,100
DATA      ENDS
;***********************************************************
STACK     SEGMENT
          DB 200 DUP ('STACK')
STACK     ENDS
CODE      SEGMENT
          ASSUME DS:DATA,SS:STACK,CS:CODE
START:    MOV AX,DATA
          MOV DS,AX
          MOV aH, 0
          MOV AL,00
          INT 10H           
;********** 定义一个宏显示
DISPLAY   MACRO b
          LEA DX,b
          MOV AH,9
          INT 21H
          ENDM
;**********************音乐地址宏
ADDRESS   MACRO A,B
          LEA SI,A
          LEA BP,DS:B
          ENDM
;***********************
          DISPLAY INFO1
          DISPLAY INFO2
          DISPLAY MUSLIST
TIGER:    ADDRESS MUS_FREG3,MUS_TIME3
          CALL MUSIC
          JMP TIGER
;******************************************发声
GENSOUND PROC NEAR
          PUSH AX
          PUSH BX
          PUSH CX
          PUSH DX
          PUSH DI
          MOV AL,0B6H
          OUT 43H,AL
          MOV DX,12H
          MOV AX,3280H
          DIV DI
          OUT 42H,AL
          MOV AL,AH
          OUT 42H,AL
          IN AL,61H
          MOV AH,AL
          OR AL,3
          OUT 61H,AL
WAIT1:    MOV CX,3314
          call waitf
DELAY1:   DEC BX
          JNZ WAIT1
          MOV AL,AH
          OUT 61H,AL
          POP DI
          POP DX
          POP CX
          POP BX
          POP AX
          RET
GENSOUND ENDP
;********************************************
waitf proc near
      push ax
waitf1:
      in al,61h
      and al,10h
      cmp al,ah
      je waitf1
      mov ah,al
      loop waitf1
      pop ax
      ret
waitf endp
;********************************************* 音乐播放
MUSIC   PROC NEAR
          PUSH DS
          SUB AX,AX
          PUSH AX                                 
FREG:     mov ah, 0bh                ;检测是否有任意键按下?
          int 21h
          cmp al,00
出现问题:JNE  RETU
          MOV DI,[SI]
          CMP DI,-1
          JE END_MUS
          MOV BX,DS:[BP]
          CALL GENSOUND
          INC SI
          INC SI
          INC BP
          INC BP
          JMP FREG
          JMP END_MUS
RETU:     DISPLAY INFO6
END_MUS: RET
MUSIC    ENDP
CODE      ENDS
          END START



代码见上。这个程序是自动播放一段音乐,然后按任意键结束。正常执行的时候,按任意键结束后,应该显示一条信息“music was stopped!”,也就是我数据段中的变量 INFO6。但是按任意键结束播放,音乐停止后,却没有显示。这是怎么回事啊?我是在音乐播放的循环体中写了一句跳转语句(红色的那行代码),然后跳转执行“RETU:     DISPLAY INFO6”

[ 本帖最后由 paul_wing 于 2012-5-14 01:17 编辑 ]
13 回复
#2
paul_wing2012-05-14 01:14
程序代码:

MUSIC   PROC NEAR
          PUSH DS
          SUB AX,AX
          PUSH AX                                 
FREG:     mov ah, 0bh                ;检测是否有任意键按下?
          int 21h
          cmp al,00
JNE  RETU
          MOV DI,[SI]
          CMP DI,-1
          JE END_MUS
          MOV BX,DS:[BP]
          CALL GENSOUND
          INC SI
          INC SI
          INC BP
          INC BP
          JMP FREG
          JMP END_MUS
RETU:     DISPLAY INFO6
END_MUS: RET
MUSIC    ENDP


主要就是这段程序中,从“JNE RETU”这句跳转到“RETU: DISPLAY INFO6”有问题。。。

[ 本帖最后由 paul_wing 于 2012-5-14 01:16 编辑 ]
#3
zklhp2012-05-14 10:57
出现问题:JNE  RETU

RETU:     DISPLAY INFO6
END_MUS: RET

对啊 跳转了没跳回来啊

你以为ret能返回 但是ret只有在返回地址压人堆栈的时候才这样做 call自动做了返回地址压栈 而跳转指令不这样

所以 肯定不会返回。。
#4
paul_wing2012-05-14 11:14
以下是引用zklhp在2012-5-14 10:57:41的发言:

出现问题:JNE  RETU

RETU:     DISPLAY INFO6
END_MUS: RET

对啊 跳转了没跳回来啊

你以为ret能返回 但是ret只有在返回地址压人堆栈的时候才这样做 call自动做了返回地址压栈 而跳转指令不这样

所以 肯定不会返回。。


你的意思是,我的程序在有按键被按下后,没有返回主程序中,所以显示不了“INFO6”?我仅仅是跳转到一条显示信息的语句啊。MUSIC这个子程序中开始不是压栈了吗?
#5
zklhp2012-05-14 11:50
每次都是你们一说我才看明白 呵呵 一方面我看的不仔细 另一方面 你要是注释写的好我不懂都应该能看明白

MUSIC   PROC NEAR
          PUSH DS
          SUB AX,AX
          PUSH AX         

这里的函数 应该是个近跳转 而且因为是用的call music 所以不需要你压栈。。。 我上面没看明白以为你是没返回 后来发现不需要返回 那 这里的几条压栈没意义 反而覆盖了返回地址

TIGER:    ADDRESS MUS_FREG3,MUS_TIME3
          CALL MUSIC
          JMP TIGER

更大的问题是 这里应该是个死循环罢 总之 我还是没看懂。。
#6
zklhp2012-05-14 11:57
还有就是这个程序貌似没有退出 按理应该是到music返回的时候程序就退出了 我理解的就是这样 不知道你的思路

你看 你的思路 我还要靠猜才能知道。。。 你觉得这样好么

再进一步

;********** 定义一个宏显示
DISPLAY   MACRO b
          LEA DX,b
          MOV AH,9
          INT 21H
          ENDM
;**********************音乐地址宏
ADDRESS   MACRO A,B
          LEA SI,A
          LEA BP,DS:B
          ENDM
;***********************

虽然宏可以这样写在代码里 但为啥不单独放在前面呢 搅合在一块 很乱啊 如果放在前面 你不用加分割线也很清晰

总之 清晰的思路是关键 如果你的思路清晰 应该能写出清晰的代码 或者 至少把你清晰的思路写在注释里

如果我又理解错了 欢迎再问 不过 建议你把你的思路写在代码的注释里 这样利人利己

如果觉得问题解决应该给分!!!最近都不给分很不好啊。。。
#7
paul_wing2012-05-15 00:45
哦。抱歉啊。
我先解释一下我的程序的运行目的吧。我的程序要的效果是:开始运行后,自动播放一段音乐(两只老虎),如果没有按键按下,则一直循环播放(主程序确实写了个死循环,目的就是这个)。如果有按键按下,则停止播放,并显示“MUSIC WAS STOPPED!”

大大根据我这个思路,看看程序为什么在按键按下后,虽然音乐结束了,却没有显示“MUSIC WAS STOPPED!”......


不管怎么说,感谢大大耐心跟进这个问题啊。。。

[ 本帖最后由 paul_wing 于 2012-5-15 00:47 编辑 ]
#8
zklhp2012-05-15 10:43
主程序确实写了个死循环

如果有按键按下,则停止播放,并显示“MUSIC WAS STOPPED!”

设计思路就有矛盾 死循环没跳出怎么能停呢

END_MUS: RET

直接在这里写成

mov ah, 4ch
int 21h

让它退出就好了 反正也已经显示了提示信息了


[ 本帖最后由 zklhp 于 2012-5-15 10:48 编辑 ]
#9
zklhp2012-05-15 10:44
更好的方法是 主程序里不要写死循环 加个对函数返回值的判断 用返回值来确定 我觉得这样比较好


[ 本帖最后由 zklhp 于 2012-5-15 10:47 编辑 ]
#10
paul_wing2012-05-15 12:23
那个死循环调用的music这个子程序。C语言里面有break这样的指令能够实现循环停止的功能(在循环体内部实现循环跳出)。我就想在程序中实现这么个功能。

不过按我上面写的程序,死循环虽然没有跳出来,但是按键按下之后,音乐确实停了。只不过没显示“music was stopped”啊(你可以把我的代码复制一下运行一下看看)。。。

如果在MUSIC子程序中写下面这一句:
mov ah, 4ch
int 21h
那么按键按下之后,就直接退出了,看不到显示的“music was stopped!”啊。我是想在按键按下之后,界面能够停留在“music was stopped!”的提示状态。不要一闪而过。。。

[ 本帖最后由 paul_wing 于 2012-5-15 12:43 编辑 ]
#11
zklhp2012-05-15 15:50
以下是引用paul_wing在2012-5-15 12:23:35的发言:

那个死循环调用的music这个子程序。C语言里面有break这样的指令能够实现循环停止的功能(在循环体内部实现循环跳出)。我就想在程序中实现这么个功能。
 
不过按我上面写的程序,死循环虽然没有跳出来,但是按键按下之后,音乐确实停了。只不过没显示“music was stopped”啊(你可以把我的代码复制一下运行一下看看)。。。
 
如果在MUSIC子程序中写下面这一句:
mov ah, 4ch
int 21h
那么按键按下之后,就直接退出了,看不到显示的“music was stopped!”啊。我是想在按键按下之后,界面能够停留在“music was stopped!”的提示状态。不要一闪而过。。。
那么按键按下之后,就直接退出了,看不到显示的“music was stopped!”啊。我是想在按键按下之后,界面能够停留在“music was stopped!”的提示状态。不要一闪而过。。。

这跟你的运行方式有关系 命令行运行就没事了

按照你的想法 程序不退出 永远执行 窗口当然不会关闭 但这是违反常规的啊 要是16位的时候有这么一个程序那要结束就只能重启电脑了。。
#12
zklhp2012-05-15 15:58
或者 退出之前有这么两句也可以

;暂停,任意键关闭
    mov ah,1
    int 21h

先输出一段话 像按什么任意键退出一类的 然后执行这个 有输入就继续 然后退出
#13
paul_wing2012-05-15 18:22
mov ah,1
int 21h
这个对我的程序没用啊。。。。。

我只想在任意键按下之后,界面停留在“music was stopped!”提示状态不要动(C语言里貌似有这个指令:getche)。。。。

目前看来只有 mov ah,4cH 然后在命令窗口中执行了。。。。多谢帮忙。。
#14
心随我意2012-05-21 17:29
以前学的时候  我也没学好。。。。。。。
1