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

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,就可以了。

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

单片机汇编语言的几个疑问
这一点C语言就比较好,以函数方式实现,少写括号编译通不过,不像汇编,少些个RET照样能通过。另外,编写程序时应养成一种习惯:对程序体中的寄存器操作尽量不要直接使用其地址,比如:MOV 30H,A,这里直接写30H不好,因为大的汇编程序对寄存器地址的调整是很常见的现象,一旦修改,程序中每个地方都...

在51单片机的汇编语言中的双周期指令说第二个周期读入操作码并丢弃...
第一个问题:双周期指令,第二周期读的是操作数,只有在第一周期读操作码的,而有几条指令是单字节的,也需要两个周期,这不是浪费时间,是因一个周期是不能完成的,这不是你想像的那样。第二个问题:要做计时,不管是倒计时还是正常计时,用延迟函数来做,这种方法计时是不准确的,只有用定时器才...

高分!!汇编语言的若干问题
是。6、高级语言是否是先编译成汇编指令再汇编成机器码,如果是这样高级语言在编译成汇编指令后如果汇编指令不能做到第三个问题那样,又是如何实现对各种高级语言和机器指令的协调统一的?高级语言,在这里就不要提了,它们是寄生的,没有根基。7、对于单片机编程是否都需要依靠汇编语言?那么硬件不同于计...

谁能帮我检查下,这个C51单片机的汇编语言有什么错误!
存在以下几个问题:1. 在按键的延时去抖动后,没有重新读取按键键值,即:L8: ACALL DELAY CJNE A,#0FFH,SAVE 这两条指令中间应插入:MOV A, P1,否则你用来比较的A还是第一次读到的A 2. 你在检测到按键按下后,没有等待键释放再去检测下一个按键。从你的程序中看,检测到按键按下后,蜂鸣...

我写了一个单片机的汇编语言,汇编没问题,但是调试的时候效果不理想,求 ...
汇编编译通过不等于程序没问题:1,缺乏两个按键同时按下的程序;2,由于K1,K2模块死循环,程序没有返回,每次都要重启电源或手动复位单片,才能通过按键 改变程序走向;3,按键没有去抖动处理容易出现误判断。4,K1的键值是001H,K2的值是002H,那么两个按键同时按下应该是003H吧,003H不是没有...

单片机C语言小疑问
你用的晶振应该是12M的吧,其实这段C程序编译成汇编就是三条MOV指令和三条DJNZ指令,程序的大部分时间是反复的执行DJNZ这条指令,DJNZ指令周期是2us,所以这段程序的时间大约是20*20*248=0.2S左右.那为什么用K=248而不是250呢,因为在一个循环(第三个for循环),即248个对变量k的DJNZ后,还会有一个...

单片机汇编语言问题
A2:SETB ET0 ;打开秒闪定时器 SETB TR0 JB P1.5,A3 A3:CLR TR0 MOV HOUR,#0 MOV MINTUE,#0 MOV SECOND,#0 1、执行"JB P1.5,A3"这句话,不管P1.5什么状态,都会执行A3 2、程序如下:A1:JNB P1.5,A2 LJMP A1 A2:SETB ET0 ;打开秒闪定时器 SETB TR0 JB P1.5,A3 ...

关于单片机汇编语言的小数问题
方法如下 先定义小数点后的N个位,1个位定义一个寄存器来储存十进制数值,假如不用管未知数的位数,那么定义5个寄存器就可以记录0.xxxxx 然后把要×的×,加的按位加,有进位就进

单片机汇编语言问题
1)MOVDPTR,#4000H;赋地址值 MOVR0,#40H MOVXA,@DPTR;片外RAM MOV@R0,A;片内RAM 2)MOVDPTR,#4000H MOVXA,@DPTR MOVDPTR,#3000H MOVX@DPTR,A 3)MOVDPTR,#0800H MOVCA,@DPTR;片内ROM MOVR0,#30H MOV@R0,A 4)MOVA,30H MOV40H,A 5)MOVA,30H SWAPA MOV40H,A 这些都是基础的......

急求:单片机MS-51,用汇编语言编写程序的问题. 高手的高分,谢谢,
实际上,不是255对应900,而是256对应900。那么:900 \/ 256 = 3.515 把0.015忽略,由此产生的误差,小于百分之一。那么,全部使用整数的运算,有:(0~255) * 35 = (0~8925)显示的时候,只是显示前3位,即可。--- 用8位的AD转换器,精度就是这样了,和算法无关。为了提高精度,应该采用分辨...

相似回答