第1个回答 2010-04-06
我仔细看了一下所有人的回答,有根本没看懂楼主问题答非所问的,也有回答的差不离的,我来切一下重点好了。
楼主这所有问题其实归根结底就是一个问题,堆栈和SP(堆栈指针)的问题
CALL指令执行时,就是先把当前程序指针压入堆栈并使SP加1,然后开始执行CALL指令调用的子程序,当遇到RET指令时,把前面压入堆栈的程序指针取出并SP减1(出栈),然后就回到CALL程序调用前位置了。
JMP指令并不会把程序指针压入堆栈更不会影响SP(当然自己在JMP后用PUSH指令除外)。自然CALL调用后使用JMP指令跳转,最后遇到RET指令一样能回到CALL程序调用前位置。就算你在JMP指令后使用PUSH指令,只要和POP成对出现,还是会回到调用前的位置,不成对?这堆栈不能这么用的。。飞了。。飞了。
中断其实和CALL指令时一样的道理,至于用RETI就如张庚(3楼)兄弟说的中断是要多处理一些标志位。
至于调用CALL多少次出错,这还是堆栈和SP的问题。
如我上面所写,CALL指令一次就得压栈一次,而你在RET指令前又来一次CALL指令,那么还得压一次,这样一直下去堆栈指针愈来愈大,就会占用程序所要使用的RAM地址,自然肯定会出错,一半51单片机默认SP为07H,而一般编程RAM地址20H开始就会被程序占用,一算就知道了,大概10几20次吧,如果你中间还是用堆栈那么就少点,如果你的程序占用RAM的地址靠后那么就多点,不过一般够用是肯定的了本回答被提问者采纳
第2个回答 2010-04-03
JMP是跳转指令,只要在合法范围内随便用,跟RET和CALL指令没多大关系,
RET和CALL才是一对,当使用CALL指令调用一个函数并把程序指针SP入栈记录当前执行位置,比如说循环延时程序时,程序转去执行子程序,程序执行到RET指令时出栈SP,返回程序执行原位置。
至于JMP指令能不能用RET返回,应该是不能的,JMP只是跳转不是调用,当执行JMP命令的时候CPU修改程序指针SP为跳转地址。他和RET指令没关系。
RETI命令和RET命令作用差不多,当CPU响应中断后,转去执行中断函数,中断函数执行到RETI命令时指示CPU中断函数结束,程序返回原位置执行,RETI与RET的区别就是前者用于中断函数的返回,后者用于一般函数的返回。
至于CALL指令执行多少次会出错,根据CPU架构不同这个有所不同,具体芯片应该可以在芯片手册里面查到。
以上JMP和CALL的说法只是象征性的概念,不代表具体指令,希望多你有所帮助。
第3个回答 2010-04-03
我个人觉得你好像把这些指令的功能弄混了,JMP(AJMP,LJMP,SJMP)指令这些指令时单纯的跳转指令,比如JMP loop 这条指令,就是程序跳转到LOOP这个地方去执行,并没有什么返回不返回的说法,除非执行过程中遇到别的指令。这几个指令的区别的跳转的距离,有短跳转,长跳转,这些你去看看指令表应该就知道了。
至于ret 是专门给子程序调用的时候用的,当你调用一个子程序,子程序执行完之后,必须要写一个ret 这个指令,用来返回你调用子程序的那句程序的位置,以便程序继续运行。
而RETI 是专门给中断子程序使用的,是用来做中断返回用的。
这两个指令跟JMP没有关系,使用的时候在子程序里依然可以使用JMP,但需要注意的是你用完JMP就不会返回到原来的地方,所以一般在子程序使用JMP不会超出本子程序的范围,否则可能会造成程序跑飞,乱套了。
CALL(ACALL,LCALL)调用中使用了JMP(AJMP,LJMP,SJMP)指令,最后使用RET能不能回到. 这个问题跟我刚才说的一样。
CALL(ACALL,LCALL)调用前的位置?
这个给你举例说吧:
.....
mov a,#00h
call loop ;这里就是call调用之前的位置
mov r1,#21h ;这里是call调用之后返回的位置
......
loop:
jc c
mov a,#01h
ret
CALL(ACALL,LCALL)指令中调用CALL(ACALL,LCALL),多少次就会出错?
这个问题我还没遇到过,一般在call中继续用call调用子程序不会出什么错误,除非你做的地址有重复,或者使用的寄存器有冲突,或者堆栈没有设计好,才会出错的,
我的回答基本就这些,这是第一次给别人回答,这些都是我自己的理解,因为我刚学的时候也遇到过类似的问题,不知道能不能对你有所帮助。