单片机汇编语言的几个疑问

1,什么时候用AJMP,什么时候用LJMP?
2,相对转移和绝对转移指令有什么区别?
3,比较大的程序如何调试,比如ds1302时钟程序,我自认为编程习惯还是比较好的,结构化的程序,编译可以通过,但运行就是有问题。

1、如果程序代码空间不紧张的话,建议你全部使用LJMP,或者如果跳转的目标段程序相隔很近,也可以使用SJMP。个人认为AJMP最麻烦:其机器码所标注的地址位从A10到A0,计11位,000H~7FFH,也就是说跳转到的地址与当前地址的A10到A0必须一样,比如:
原来AJMP地址为:07F8H,目标地址:07F0H,如果调试软件修改后,变为
AJMP地址为:0800H,目标地址:07F8H,A11不一样,不在一页范围,此时还得将其改成LJMP,否则编译出错。其实就省了一个字节,执行时间上都是2个机器周期,没区别,所以犯不上。如果像此例,使用SJMP倒是个较好的选择,只是要求你对代码间的间隔有数才行。
总之,尽量用LJMP吧。

2、二者区别其实就是转移的目标是绝对地址,还是针对当前转移指令所在地址的相对偏移量
【绝对转移】51中只有AJMP、LJMP是绝对转移指令,都是直接跳转到固定地址。我们平时写的比如LJMP MAIN语句,源程序中并未表示出这一点,假设MAIN标志的程序段是从0102H开始的,此句编译后的机器码是02 01 02,02代表LJMP跳转,后两个字节0102则为目标地址,由于使用了2个字节指明目标地址,所以其范围就是整个64K的空间,没有限制;AJMP在这一点上就要差些,只能在所在的2K页内跳转。
【相对转移】剩下的转移指令都是相对转移指令,包括SJMP,它们是以当前语句的下一条语句所在地址为准,PC值向前或向后偏移数个字节地址开始执行,偏移量范围从-128到+127,以补码方式存在。比如
ORG 0100H
NO1: CLR A
SJMP NO1
编译后地址及机器码:
0100H: 0E4H (CLR A)
0101H: 80H 0FDH (SJMP NO1,从0103跳回0100,倒退3字节,3的补码即取反+1=FDH
0103H: 00H

3、要想能高效的调试大的汇编程序,首先要求程序本身的编制应该规范。关于这一点我有些感触,就算是经验吧,供参考(我曾经用汇编做过50多K机器码的程序)。
单片机的执行其实是单一线程的,一般只有两种情况会偏离原来的流程,一种是中断服务子程序,注意别忘了使用RETI;还有就是普通子程序,别忘了使用RET;再加上注意出栈、入栈操作,而且该操作因成对并保证先进后出原则,这样的话才真正做到模块化编程,调试时才能不理睬其它部份,单独调试某个模块,提高效率。这一点C语言就比较好,以函数方式实现,少写括号编译通不过,不像汇编,少些个RET照样能通过。
另外,编写程序时应养成一种习惯:对程序体中的寄存器操作尽量不要直接使用其地址,比如:MOV 30H,A,这里直接写30H不好,因为大的汇编程序对寄存器地址的调整是很常见的现象,一旦修改,程序中每个地方都要改,容易遗漏,一旦遗漏,非常难找原因的。可以用EQU伪指令对其定义,程序体中使用。同样,这一点C语言要好的多,至少不需要去分配寄存器了。
还有一个最容易出错的地方,就是关于标志位C:比如CJNE指令,它的判断是会影响C标志位的,如果程序后面有对C标志位判断的语句又没有考虑这种情况,问题极难查。很多人包括我自己会忽略这种细节。这类问题只能靠细致了。

最后谈谈调试
调试过程一般都是逐个模块(子程序)分别调试,完成一个再检查下一个,不能指望一上来就正确。调试完后还要多次、多人测试,自己有时形成了固定思维,发现不了问题。
终极方法:分部仿真设断点甚至于单步执行。对一些外部输入可以采用到断电后修改寄存器数值的方法来模拟。当然最理想的情况是不用,只是初期恐怕是免不了的。比如对上面所说的C标志位问题,我个人当初几乎都是这样找出的问题

大的汇编程序的调试确实比较麻烦,首先要求你对软件流程很清晰,对单片机的运行模式也要很了解。至于你现在的程序如果有问题,我建议还是采用仿真设断点的方式来找问题,尤其是如果搞单片机的时间不长的话,这样其实可能更快些。

希望所说能对你有所帮助。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-08-04
1、(R1)=20H 不是一条指令,而只是一种说明,表明R1寄存器中的内容是20H。这个20H是地址还是数据,与这个说明无关。

2、在指令 MOV @R1,#40H 中,@R1 是间接寻址方式,表明R1中的内容是地址,指令的功能表明是将立即数40H传送到R1指定的地址中。

3、在指令中容易混淆的是立即数与直接地址,立即数的特征是有一个前缀#,直接地址没有这个前缀。

无论程序在何处,都可以跳到你要的地方,同样LCALL也是非常好用,它是长调用子程序,也是无论程序执行到何处,遇到它都可以调内存里任何一个位置子程序

所以我用最简单的一句话告诉你,在你需要跳转的时候就用LJMP,在你需要调程序的时候就用LCALL

引用:

⑵ JMP NEAR PTR label 近转移(near jump)
近转移是JMP指令的缺省格式,可以写为"JMP label"。它可在当前代码段内转移,机器指令的操作码是E9,位移量是16位的带符号补码数。指令中的转向地址可以是直接寻址方式、寄存器寻址方式、寄存器间接方式和存储器寻址方式。

● JMP label 直接转移(direct jump)
执行操作:(IP) ← OFFSET label = (IP)当前+16位位移量
转移的目标地址在指令中可直接使用符号地址,由于位移量为16位,它的转移范围应是-32768至+32767,也就是说,近转移指令可以转移到段内的任一个位置。

● JMP reg 寄存器间接转移(register indirect jump)
执行操作:(IP) ← (reg)
转移的目标地址在寄存器中,例如指令"JMP BX"执行的结果,将BX的内容送给IP。

● JMP WORD PTR OPR 存储器间接转移(memory indirect jump)
执行操作:(IP) ← (PA+1,PA)
存储器的物理地址PA由指令中的寻址方式确定,JMP指令执行的结果,把PA单元的字内容送到IP寄存器中。例如"JMP WORD PTR [DI]",物理地址PA = (DS)×24+(DI),指令执行的结果是(IP)= (PA+1,PA)。
Write_Ds1302_Byte(address);
Write_Ds1302_Byte(dat);
这两个函数是网DS1302中写地址和数据的,根据DS1302的时序,可以看明白顺序。
第2个回答  2011-08-04
1. AJMP的跳转范围有限,只能在当前PC所处的2kB块内跳转。LJMP的跳转范围为全64kB空间。
2. 所谓相对,是指相对于当前地址进行跳转,通俗地说就是“前进n步”或“后退n步”。所谓绝对,就是直接跳转到明确指定的地址,通俗地说就是“跳到xxxx位置”。
3. 程序部分分模块,逐步添加模块并运行调试,这样可以逐个排除问题。如果有串口或其它通讯接口可以输出调试信息,有硬件仿真更好。
第3个回答  2011-08-04
都是些 很基本的问题。 基础啊。
1,什么时候用AJMP,什么时候用LJMP?
是 短距离跳转 和 长距离跳转的区别。 通常不同的单片机 都支持相应的伪指令,比如JMP。
编译器自动 根据实际 来编译。 具体要看 那款单片机了。
2,相对转移和绝对转移指令有什么区别?
相对转移: 根据相对地址量来转移。 绝对转移:向绝对地址转移
3,比较大的程序如何调试
一般调试都是 分全速运行, 单步运行 和 断点运行。 根据实际需要了
第4个回答  2023-02-28

LJMP、AJMP、SJMP,都是无条件转移指令。

区别,你就不用深究了。

你编程时,仅需使用一条:JMP,就可以了。

编译软件,会自动帮你,编译成为适合的机器码。

相似回答