是将R4、R3中的双字节被乘数与R5中的字节乘数相乘,乘积存放在地址为32H~30H 3个存储单元中((答案不惟一) 。 解: 涉及到寄存器,用汇编实现: ORG 0000H MOV SP,#49H MOV A,R3 MOV B,R5 MUL AB
MOV R0,#30H
MOV @R0,A ;将低8位存入30H INC R0 MOV R1,B MOV A,R4 MOV B,R5 MUL AB ADD A,R1
MOV @R0,A; 将中间8位存入31H MOV A,B
ADDC A,#00H ; 将中间8位的进位加入A中 INC R0
MOV @R0,A ;将高8位存入32H SJMP $ ;程序在此死循环 END
10.编写程序,用 30H 单元内容除以 40H 单元内容,商送入 50H 单元,余数送入 51H 单元。 (答案不惟一)
解: 涉及直接地址,用汇编实现: ORG 0000H MOV SP,#49H
MOV A,30H ;被除数 MOV B,40H;除数 DIV AB;A/B
MOV 50H,A ;商存50H单元 MOV 51H,B ;余存51H单元 SJMP $ ;程序在此死循环 END
11.已知: (30H)= 55H,(31H)= 0AAH。分别写出完成下列要求的指令,并写出32H 单元的内容。 解: (1)(30H)&(31H)→(32H); DBYTE[0x32]= DBYTE[0x30]& DBYTE[0x31];0x00 (2)(30H)|(31H)→(32H); DBYTE[0x32]= DBYTE[0x30]| DBYTE[0x31];0xff (3)(30H)^(31H)→(32H); DBYTE[0x32]= DBYTE[0x30]^DBYTE[0x31];0xff 12.十进制调整指令DA起什么作用?用在何处? 答: 十进制调整指令如下: DA A
功能是把A中二进制码自动调整成二-十进制码(BCD码)。用于对BCD码的加法结果
进行调整。
13.80C51 指令系统中有了长跳转 LJMP、长调用 LCALL 指令,为何还设置了短跳转 AJMP、短调用ACALL指令?在实际使用时应怎样考虑?
答: LJMP addr16,LCALL addr16,指令码中的目标地址均是16位的,所以可以指向64KB 程序存储器空间任意位置。
AJMP addr11,ACALL addr11,指令码中的目标地址均是 12 位的,所以可以指向 2KB 程序存储器空间任意位置。
当使用的程序存储器空间在 2KB 之内或产生的代码长度在 2KB 之内时所有的跳转和调 用可以使用 AJMP ,ACALL 指令。否则建议使用 LJMP,LCALL。高级语言编译器根据所选目标器件和代码情况自动生成。
14.写出下列短跳转指令中标号L00的取值范围。 37FFH AJMP L00
答: 最大转移地址为:37FFH +2KB 15.设堆栈指针(SP)= 60H: (1)2500H LCALL L00 ?? ……
(2)2700H MOV A,#03H ?? …… (3)2750H RET
执行(1)指令后:(SP)、((SP))、((SP-1))、(PC) 各为多少?执行(2)指令后:(SP)、(PC) 为多少?若将(1)指令改为ACALL L00,标号L00的取值范围是多少? 答:
执行(1)指令后,(SP)=62H,((SP))=25H,((SP-1))=03H,(PC)= L00; 执行(2)指令后,(SP)=60H,(PC)= 2702H;
若将(1)指令改为ACALL L00,标号L00的取值范围是当前PC的高5位,加上低11位 从全0变全1;例如:2500H ACALL L00,当前PC=2500H,PC高5位是00100,则L00 取值范围是:[00100, 00000000000~00100, 11111111111]
16.为什么SJMP指令的rel=$时,将实现单指令的无限循环? 答: $表示本指令所处地址, 该指令相当于:Here:SJMP Here 17.有程序如下: CLR C CLR RS1 CLR RS0 MOV A,#38H MOV R0,A MOV 29H,R0 SETB RS0 MOV R1,A MOV 26H,A MOV 28H,C
(1)区分哪些是伪操作指令?哪些是字节操作指令? (2)写出程序执行后,片内RAM有关单元的内容。 (3)如fosc=12MHz,计算这段程序的执行时间。 答: (1)(2)
CLR C;答:位操作指令 (C)= 0 CLR RS1;答:位操作指令 (RS1)= 0 CLR RS0;答:位操作指令 (RS0)= 0
MOV A,#38H;答:字节操作指令 A=38H MOV R0,A;答:字节操作指令R0=(A)=38H
MOV 29H,R0;答:字节操作指令 (29H)=(R0)=38H SETB RS0;答:位操作指令 (RS0)=1
MOV R1,A;答:字节操作指令 R1=(A)=38H MOV 26H,A;答:字节操作指令 (26H)=(A)=38H MOV 28H,C;答:位操作指令 (28H)=(C)=0
(3)如fosc=12MHz,这段程序的执行时间=11μs 18.请用位操作指令,求下列逻辑方程: (1)P1.7 ACC.0&(B.0 P2.0) P3.0 =+ + (2)PSW.5 P1.0&ACC B.6&P1.4 =+ (3)PSW.5 P1.7&B.4 C ACC&P1.0 =++
答: (1)P1_7=(ACC_0)&&(( B_0||P2_0)||(~P3_0));
答: (2)PSW_5=(P1_0&&(~ACC))||( B_6&&(~P1_4)) //此处实际上是取ACC.0 答: (3)PSW_5=(~(P1_7)&&B_4)||CY||((~ACC)&&P1_0) //此处实际上是取ACC.0 19.写出下列各条指令的机器码,并逐条写出依次执行每条指令后的结果和 PSW 的内 容:
(1)CLR A
(2)MOV A, #9BH (3)MOV B, #0AFH (4)ADD A, B
答: (1)CLR A //答案:机器码:E4 (A)=0 , (B)=0, PSW=0x00 (2)MOV A, #9BH //答案:机器码:749B (A)=0x9B , (B)=0, PSW:0x01
(3)MOV B, #0AFH //答案:机器码:75F0AF (A)=0x9B , (B)=0xAF, PSW:0x01 (4)ADD A, B //答案:机器码:25F0 (A)=0x4A , (B)=0xAF, PSW:0xc5 20.伪指令与汇编指令有何区别?说出常用的5种伪指令的作用。 答:
● 汇编指令,编译后产生机器码的指令;
● 伪指令,仅供汇编程序使用,编译后不产生机器码的指令。 常用的5种伪指令如下:
1.设置起始地址ORG(Origin) 指令格式:ORG nn
作用:将ORG nn后的程序机器码或数据存放在以nn为首地址的存储单元中。如伪指令 ORG 1000H,是将目标程序从地址1000H处开始存放的。 2.定义字节DB或DEFB(Define Byte) 指令格式:[LABEL] DB N1,N2,?,Nm
作用:将DB后的8位字节数据N1,N2,?,Nm依次存入以标号LABEL为首地址的 存储单元中。若无标号,则N1,N2,?,Nm依次存放在DB上一条指令之后的存储单元中。
3.定义字DW或DEFW(Define Word)
指令格式:[LABEL] DW NN1,NN2,?,NNm
作用:将DW后的16位字数据NN1,NN2,?,NNm依次存放到以标号LABEL为首 地址的存储单元中,若无标号,则 NN1,NN2,?,NNm 依次存放在 DW 上一条指令之后的存储单元中。
4.为标号赋值EQU(Equate) 指令格式:LABEL EQU nn(或n)
作用:将16位地址nn(或8位地址n)赋给标号LABEL。 5.结束汇编END 指令格式:END
作用:汇编程序编译源程序时,遇到伪指令END,不管其后是否还有其他指令都将停止 编译。
21.在单片机应用开发系统中,C语言编程与汇编语言编程相比有哪些优势?
答: 汇编语言有执行效率高的优点,但其可移植性和可读性差,并且它本身就是一种编程效率低的低级语言,这些都使它的编程和维护极不方便,从而导致了整个系统的可靠性也较差。而使用C语言进行单片机应用系统的开发,有着汇编语言编程不可比拟的优势。 (1)编程调试灵活方便 (2)生成的代码编译效率高 (3)完全模块化 (4)可移植性好
(5)便于项目维护管理
22.在C51中有几种关系运算符?请列举。 答: C51中有6种关系运算符: > 大于 < 小于
>= 大于等于 <= 小于等于 == 测试等于 != 测试不等于
23.在C51中为何要尽量采用无符号的字节变量或位变量?
答: 采用无符号的字节变量或位变量可提高代码效率的方法就是减小变量的长度,使用ANSI C 编程时,一般习惯于对变量使用 int 类型,而对于像 80C51 这类 8 位的单片机来说这是一种极大的浪费。80C51 单片机机器指令只支持字节和位变量,所以应该仔细考虑所声明的变量值的可能的取值范围,然后选择合适的变量类型。尽可能地选择变量类型为char、unsigned
char 或bit,它们只占用1B或1位。
24.为了加快程序的运行速度,C51中频繁操作的变量应定义在哪个存储区?
答: 局部变量和全局变量可以被定义在任何一个存储区中,根据前面的讨论,把经常使用的变量放在内部RAM中时,可使程序的速度得到提高。除此之外,还缩短了程序代码,因为外部存储区寻址的指令,相对要麻烦一些。考虑到存取速度,推荐读者按 data→idata→pdata→xdata 的顺序使用存储器,当然要记得在idata空间中留出足够的堆栈空间。 25.为何在C51中避免使用float浮点型变量?
答: 在 80C51 单片机系统上使用 32 位浮点数是得不偿失的,这样做会浪费单片机大量的存储器资源和程序执行时间。一定要在系统中使用浮点数的时候,可以通过提高数值数量级或使用整型运算代替浮点运算。在运算时,可以进行定点运算的尽量进行定点运算,避免进行浮点运算。尽量减少乘除法运算,如*2n
或/2n,可以使用移位操作代替乘除法运算,这样不仅可以减少代码量,同时还能大大提高程序执行效率。处理ints和longs比处理doubles和floats要方便得多,代码执行起来会更快,C51编译器也不用连接处理浮点运算的模块。 26.如何定义C51的中断函数?
答: 80C51的中断系统十分重要,C51编译器允许在C语言源程序中声明中断和编写中断服务程序,从而减轻了采用汇编程序编写中断服务程序的烦琐程度。通过使用 interrupt 关键字来实现。定义中断服务程序的一般格式如下: void 函数名( ) interrupt n [using m]
关键字interrupt后面的n是中断号,n的取值范围为0~31。编译程序从8n+3处产生中 断向量,即在程序存储器8n+3地址处形成一条长跳转指令,转向中断号n的中断服务程序。 中断号对应着 IE 寄存器中的使能位,换句话说 IE 寄存器中的 0 位对应着外部中断 0,相应的外部中断0的中断号是0。中断号0~4对应中断源的关系如主教材表5.14所示。 中断号和中断源的对应关系
中 断 号 n 中 断 源 中 断 向 量 0 外部中断0 0003H 1 定时器0 000BH 2 外部中断1 0013H 3 定时器1 001BH 4 串行口 0023H
using m 指明该中断服务程序所对应的工作寄存器组,取值范围为 0~3。指定工作寄存 器组的缺点是所有被中断调用的过程都必须使用同一个寄存器组,否则参数传递会发生错误。
通常不设定using m,除非保证中断程序中未调用其他子程序。 设置一个定时器中断服务程序的例子如下: #include
#define RELOADTH 0x3C #define RELOADTL 0xB0
extern unsigned int time0_counter; void timer0(void) interrupt 1{
TR0=0; /*停止定时器0*/ TH0=RELOADTH; /* 50ms后溢出*/ TL0=RELOADTL;
TR0=1; /*启动T0*/
time0_counter++; /*中断次数计数器加1*/ printf(\,time0_counter); }
使用C51编写中断服务程序,程序员无须关心ACC、B、DPH、DPL、PSW等寄存器的 保护,C51编译器会根据上述寄存器的使用情况在目标代码中自动增加压栈和出栈。
习题5
1.80C51 有几个中断源,各中断标识是如何产生、如何复 0 的?CPU 响应中断时,其 中断入口地址各是多少?
答: 80C5l共有3类5个中断源,分别是2个外部中断源、2个定时中断源、1个串行口接