第4章

汇编语言程序设计

系统讲解51单片机汇编语言的程序设计方法,包括顺序、分支、循环、查表、子程序等核心技术

01

4.1 顺序程序设计

顺序程序是按照指令编写顺序逐条执行的程序结构,无分支、循环等控制逻辑。其核心是利用基本指令实现数据处理。

基本指令应用

  • 数据传送(MOV、MOVX、MOVC)
  • 算术运算(ADD、SUBB、INC)
  • 逻辑运算(ANL、ORL、XRL)

伪指令支持

  • ORG(指定程序起始地址)
  • EQU(符号定义)
  • DATA(数据地址赋值)

典型场景

  • 简单数据处理
  • 初始化设置
  • I/O端口直接操作

示例代码:点亮LED并延时

ORG 0000H
MOV P2, #0FEH  ; 点亮第一个LED
MOV R7, #20    ; 延时参数
DELAY:
DJNZ R7, DELAY  ; 循环延时
SJMP $         ; 程序暂停
END
02

4.2 分支程序设计

通过条件判断实现程序流向控制,分为单分支、多分支结构。

条件转移指令

  • CJNE(比较转移)
  • JZ(判零转移)
  • JB(判位转移)

多分支实现

  • 使用散转程序(JMP @A+DPTR)
  • 结合数据表格实现多路分支

设计要点

  • 条件判断逻辑清晰
  • 避免分支嵌套过深

示例代码:根据数值点亮不同LED

CJNE A, #10, NEXT  ; 比较A与10
MOV P2, #0FFH      ; 相等时全灭
SJMP END
NEXT:
JNC HIGH           ; A>10则跳转
MOV P2, #0FEH      ; A<10点亮第一个LED
SJMP END
HIGH:
MOV P2, #01H       ; A>10点亮最后一个LED
END:
SJMP END

要点提示

分支程序设计的关键是合理使用条件转移指令,确保每个分支都有明确的出口,避免程序陷入死循环。

03

4.3 循环程序设计

通过循环结构重复执行某段程序,分为计数循环和条件循环。

循环三要素

  • 初始化
  • 循环体
  • 循环控制(DJNZ、CJNE等)

典型应用

  • 延时程序
  • 数据块处理
  • 查表遍历

注意事项

  • 避免死循环
  • 合理分配寄存器资源

示例代码:数据块求和

MOV R0, #30H      ; 数据块起始地址
MOV R7, #10       ; 数据长度
CLR A             ; 累加器清零
LOOP:
ADD A, @R0        ; 累加数据
INC R0            ; 指针后移
DJNZ R7, LOOP     ; 未完成继续循环
MOV 40H, A        ; 保存结果

技巧提示

循环程序设计时,应先初始化循环变量和指针,然后在循环体中更新这些变量,最后进行循环条件判断。

04

4.4 查表程序设计

通过查表指令(MOVC)快速获取预存数据,适用于非线性运算或固定参数访问。

查表方式

  • 直接查表(表格起始地址固定)
  • 变址查表(通过DPTR+A定位)

表格定义

  • DB(定义字节)
  • DW(定义字)

应用场景

  • LED段码转换
  • 温度补偿
  • 代码转换

示例代码:数码管段码查表

MOV DPTR, #SEG_TAB  ; 段码表首地址
MOV A, R2           ; 待转换数据
MOVC A, @A+DPTR     ; 查表
MOV P0, A           ; 输出显示
SEG_TAB:
DB 0C0H, 0F9H, 0A4H, 0B0H  ; 0-3的段码

应用示例

查表程序广泛应用于LED数码管显示、LCD字符显示、传感器数据校准等场景,可以大大简化程序逻辑。

05

4.5 子程序设计和参数传递

将重复使用的代码模块化,通过调用指令(ACALL、LCALL)实现复用。

子程序结构

  • 入口参数处理
  • 功能实现
  • 出口参数返回
  • 现场保护

参数传递方法

  • 寄存器传递:利用R0-R7传递数据
  • 内存传递:通过固定地址单元交换数据
  • 堆栈传递:使用PUSH/POP指令压栈出栈

注意事项

  • 堆栈深度计算避免溢出
  • 子程序嵌套不超过3层

示例代码:数据乘法子程序

MAIN:
MOV R0, #50H       ; 入口参数地址
LCALL SUM          ; 调用求和子程序
SJMP $

SUM:
PUSH ACC           ; 保护现场
PUSH B
MOV A, @R0
MOV B, #10
MUL AB             ; 计算50H单元数据×10
POP B              ; 恢复现场
POP ACC
RET

要点提示

子程序设计时,应注意现场保护和恢复,确保子程序执行后不影响主程序的运行环境。参数传递方式应根据实际需求选择。

06

4.6 程序设计实例

综合应用多种程序设计方法实现具体功能。

实例1:LED流水灯(查表法)

ORG 0000H
MOV DPTR, #LED_TAB  ; 流水灯模式表
MOV R2, #0         ; 初始偏移量
LOOP:
MOV A, R2
MOVC A, @A+DPTR    ; 查表
MOV P2, A
LCALL DELAY        ; 调用延时子程序
INC R2
CJNE R2, #8, LOOP  ; 循环8次
SJMP LOOP

LED_TAB:
DB 0FEH, 0FDH, 0FBH, 0F7H  ; 流水灯模式
DB 0EFH, 0DFH, 0BFH, 7FH

DELAY:
MOV R7, #20        ; 延时子程序
D1: MOV R6, #250
D2: DJNZ R6, D2
DJNZ R7, D1
RET
END
程序功能

控制8个LED循环点亮,形成流水灯效果。

技术要点
  • 查表法实现多种显示模式
  • 子程序实现延时控制
  • 循环结构实现重复显示

实例2:按键控制数码管显示

ORG 0000H
MOV P1, #0FFH      ; 初始化按键端口
MOV 30H, #0        ; 显示数值初始化为0
LOOP:
JB P1.0, DISP      ; 检测按键是否按下
ACALL DELAY        ; 消抖
JB P1.0, DISP
INC 30H            ; 数值加1
CJNE 30H, #10, DISP
MOV 30H, #0

DISP:
MOV A, 30H
MOV DPTR, #SEG_TAB
MOVC A, @A+DPTR
MOV P0, A
SJMP LOOP

SEG_TAB:
DB 0C0H, 0F9H, 0A4H, 0B0H  ; 0-3的段码
DB 099H, 092H, 082H, 0F8H  ; 4-7的段码
DB 080H, 090H              ; 8-9的段码
END
程序功能

通过按键调整数码管显示的数字(0-9循环)。

技术要点
  • 按键检测与消抖处理
  • 分支结构实现数值循环
  • 查表法实现数码管段码转换
07

4.7 本章总结

本章系统讲解了51单片机汇编语言程序设计的核心方法。

核心知识点

  • 顺序程序是基础,分支和循环实现逻辑控制,查表提升效率,子程序增强复用性。
  • 参数传递需根据场景选择合适方法,堆栈使用时注意溢出问题。
  • 实际编程中需结合硬件特性,合理分配资源,确保程序可靠性。

学习建议

  • 通过实例练习,掌握从需求分析到代码实现的完整流程。
  • 熟悉各类指令的使用场景,培养代码优化意识。
  • 多进行程序调试,理解指令执行流程和寄存器状态变化。

进阶学习

掌握本章内容后,可进一步学习中断系统、定时器/计数器、串行通信等高级功能,以及复杂程序的模块化设计方法。