3127 字
16 分钟
sdcc汇编伪指令
汇编助记符中的符号含义
| 符号 | 含义 | 说明 |
|---|---|---|
| Rn | 工作寄存器 R0~R7 | n 可取 0~7,表示当前寄存器组中的寄存器 |
| Ri | 间接寻址寄存器 R0 或 R1 | i 可取 0 或 1,用于间接寻址 |
| @Ri | 以 Ri 中的值为地址,访问该地址的数据 | 间接寻址方式,Ri 中存放的是内存地址 |
| #data | 立即数 | 直接跟在指令后的常数,如 #30H |
| direct | 直接地址 | 8位内部 RAM 地址或 SFR 地址,如 30H 或 P1 |
SDCC伪指令详细说明及示例
一、段定义伪指令(.area)
1. 基本格式
.area 段名 (属性1,属性2,...) [重定位类型]2. 常用段类型
; 代码段(程序存储器).area CSEG (CODE) ; 常规代码段.area HOME (CODE) ; 起始段(0x0000-0x00FF).area GSINIT (CODE) ; 全局变量初始化代码.area GSFINAL (CODE) ; 初始化后的代码
; 数据段.area DSEG (DATA) ; 内部可直接寻址数据(0x30-0x7F).area ISEG (DATA) ; 内部间接寻址数据(0x80-0xFF).area OSEG (DATA) ; 覆盖数据段.area XSEG (XDATA) ; 外部数据存储器.area ESEG (EDATA) ; 扩展数据存储器(STC8G特有)
; 其他.area RSEG (ABS) ; 绝对定位段.area ASEG (ABS) ; 绝对段(已过时).area BSEG (BIT) ; 位寻址区(0x20-0x2F)3. 段属性
CODE- 程序代码DATA- 内部RAM数据XDATA- 外部RAM数据EDATA- 扩展RAM数据(STC8G)ABS- 绝对地址BSS- 未初始化数据BIT- 位数据OVR- 可覆盖段REL- 可重定位段CON- 常量段
4. 示例
; 定义绝对地址中断向量表.area VEC (ABS).org 0x0000 ljmp _main ; 复位向量.org 0x0003 ljmp _ext0_isr ; 外部中断0.org 0x000B ljmp _timer0_isr ; 定时器0中断
; 代码段.area CSEG (CODE)_main: mov SP, #0x80 ; 设置堆栈指针
; 内部数据段.area DSEG (DATA)counter: .byte 0x00 ; 单字节变量buffer: .ds 16 ; 16字节缓冲区
; 外部数据段.area XSEG (XDATA)large_buffer: .ds 1024 ; 1KB外部缓冲区
; 位寻址区.area BSEG (BIT)flag1: .dbits 1 ; 定义1个位flags: .dbits 8 ; 定义8个位(1字节)二、数据定义伪指令
1. 字节数据
; 定义字节(8位).byte value1, value2, ... ; 定义字节序列.db value1, value2, ... ; 同.byte
; 示例data1: .byte 0x12 ; 单个字节table: .byte 0, 1, 2, 3, 4 ; 数组str: .byte 'H','e','l','l','o',0 ; 字符串2. 字数据
; 定义字(16位).word value1, value2, ... ; 定义字序列(小端序).dw value1, value2, ... ; 同.word
; 示例vectors: .word 0x0000, 0x1000, 0x2000 ; 地址表const: .dw 0x1234, 0x5678 ; 16位常量3. 双字数据
; 定义双字(32位).long value1, value2, ... ; 32位数据.dl value1, value2, ... ; 同.long
; 示例long_val: .long 0x12345678 ; 32位值float_val: .long 0x4048F5C3 ; 浮点数(3.14的IEEE754表示)4. 浮点数
; 定义浮点数.float value1, value2, ... ; 单精度浮点数
; 示例pi: .float 3.1415926temp: .float 25.55. 字符串
; ASCII字符串.ascii "string" ; 无结束符.asciz "string" ; 以\0结尾
; 示例msg1: .ascii "Error" ; 长度5msg2: .asciz "Hello" ; 长度6(含\0)6. 保留空间
.ds size ; 保留size字节空间.blkb size ; 同.ds(块)
; 示例buffer: .ds 100 ; 100字节缓冲区stack: .blkb 32 ; 32字节堆栈空间7. 位数据
; 位定义(仅用于BSEG段).dbits size ; 定义size个位
; 示例.area BSEG (BIT)flags: .dbits 8 ; 8个标志位status: .dbits 1 ; 单状态位三、符号定义伪指令
1. 常量定义
; 等值定义.equ symbol, value ; 定义符号常量.set symbol, value ; 同.equ(可重复定义)= symbol = value ; 另一种形式
; 示例.equ BUFFER_SIZE, 256 ; 定义常量.set COUNTER_MAX, 1000TIMEOUT = 5000 ; 使用等号2. 全局符号声明
.globl symbol ; 声明全局符号.global symbol ; 同.globl.gblel symbol ; 声明全局外部符号
; 示例.globl _main ; C主函数.globl _isr_timer0 ; 中断服务函数3. 外部符号声明
.extern symbol ; 声明外部符号.external symbol ; 同.extern
; 示例.extern _printf ; 外部C函数.extern buffer ; 外部变量四、条件汇编伪指令
1. 基本条件
; 条件块.if condition ; 开始条件.else ; 否则分支.endif ; 结束条件
; 示例.if DEBUG == 1 mov A, #0x55 ; 调试代码.else mov A, #0xAA ; 发布代码.endif2. 符号条件
; 符号检查.ifdef symbol ; 如果符号已定义.ifndef symbol ; 如果符号未定义
; 示例.ifdef USE_UART call uart_init ; 如果定义了USE_UART.endif
.ifndef OPTIMIZE nop ; 如果没有优化.endif3. 比较条件
; 比较表达式.ifeq expression ; 如果等于.ifne expression ; 如果不等于.ifgt expression ; 如果大于.ifge expression ; 如果大于等于.iflt expression ; 如果小于.ifle expression ; 如果小于等于
; 示例.ifeq VERSION-2 ljmp legacy_code ; VERSION==2时.else ljmp new_code ; 其他情况.endif五、宏定义与使用
1. 基本宏定义
; 宏定义.macro macroname [param1, param2, ...] ; 定义宏 ; 宏体.endm ; 结束宏
; 示例:延时宏.macro DELAY cycles mov R7, #(\cycles & 0xFF) ; 使用参数 djnz R7, $.endm
; 使用宏DELAY 100 ; 扩展为:mov R7, #100; djnz R7, $DELAY 255 ; 扩展为:mov R7, #255; djnz R7, $2. 带参数的宏
; 带多个参数的宏.macro MOV16 src, dst mov A, \src ; 参数前加反斜杠 mov \dst, A mov A, \src+1 mov \dst+1, A.endm
; 使用MOV16 #0x1234, R6 ; 将16位值传送到R6:R73. 局部标签宏
; 带局部标签的宏.macro DELAY_MS ms mov R5, #\ms1$: ; 局部标签(数字+$) mov R6, #2002$: mov R7, #250 djnz R7, $ djnz R6, 2$ djnz R5, 1$.endm4. 条件宏
; 条件判断宏.macro BIT_SET reg, bit .if \bit < 8 setb \reg.\bit ; 使用位操作符 .else .error "Bit out of range" .endif.endm
; 使用BIT_SET P1, 0 ; setb P1.0BIT_SET ACC, 3 ; setb ACC.35. 嵌套宏
; 宏嵌套.macro PUSH_REG reg push \reg.endm
.macro PUSH_REGS regs .irp reg, \regs ; 迭代参数列表 PUSH_REG \reg .endm.endm
; 使用PUSH_REGS ACC, B, PSW ; 压栈多个寄存器6. 宏函数示例
; 计算平方的宏函数.macro SQUARE x, result mov A, #\x mov B, A mul AB mov \result, A ; 低8位 mov \result+1, B ; 高8位.endm
; 使用SQUARE 5, square_result
; 带返回值的宏.macro ADD16 a, b mov A, \a add A, \b mov R0, A mov A, \a+1 addc A, \b+1 mov R1, A ; 结果在R0:R1中.endm六、包含文件与模块化
1. 包含文件
.include "filename.inc" ; 包含汇编文件.include <stddef.h> ; 包含C头文件(需要-i指定路径)
; 示例.include "stc8g.h".include "macros.inc".include "config.inc"2. 模块化组织
; 主文件 main.asm.module main.globl _main
.include "uart.inc".include "timer.inc"
_main: call uart_init call timer_init ; ...
; 子模块 uart.inc.module uart.globl uart_init, uart_send
uart_init: ; ... ret
uart_send: ; ... ret七、地址控制伪指令
1. 地址定位
.org address ; 设置当前位置.radix base ; 设置数字基数(2,8,10,16)
; 示例.radix 16 ; 设置为16进制.org 1000H ; 从1000H开始 .byte 1,2,3,4.org 2000H ; 跳转到2000H .word 1234H2. 对齐
.even ; 对齐到偶数地址.odd ; 对齐到奇数地址.align power ; 对齐到2^power边界
; 示例.align 4 ; 对齐到16字节边界data: .ds 10
.even ; 确保下面代码在偶地址code: mov A, #0八、列表控制伪指令
1. 列表文件控制
.list ; 开启列表.nolist ; 关闭列表.lst ; 生成列表文件.nolst ; 不生成列表文件
; 示例.nolist ; 不列出包含文件内容.include "macros.inc".list ; 恢复列表2. 其他控制
.title "标题" ; 设置标题.sbttl "子标题" ; 设置子标题.page ; 分页.width columns ; 设置列宽九、标签的 : 和 :: 区别
1. 单冒号 :(局部标签)
; 局部标签(默认)label1: ; 局部标签,文件内可见 nop
; 示例loop: ; 局部循环标签 djnz R7, loop ; 可访问
func1: call subfunc ret
subfunc: ; 另一个局部标签 nop ret2. 双冒号 ::(全局标签)
; 全局标签label2:: ; 全局标签,外部可访问
; 示例.globl _main ; 需要配合.globl声明_main:: ; C入口函数(全局) mov SP, #0x80
; 中断服务函数(全局)_ext0_isr:: push PSW ; ... 中断处理 pop PSW reti
; 在另一个文件中可这样引用.extern _main ; 声明外部全局符号.extern _ext0_isr3. 标签作用域规则
; 文件: module1.asm.local_label: ; 仅本文件可见 nop
global_label:: ; 全局可见(自动.globl) nop
.globl exported_label ; 需要显式声明exported_label: ; 全局可见(需.globl) nop
; 文件: module2.asm.extern global_label ; 引用全局标签.extern exported_label
call global_label ; 可调用call exported_label ; 可调用; call local_label ; 错误!不可访问4. 数字标签(局部)
; 数字标签(自动局部)1: ; 数字标签,可重复定义 nop jb P1.0, 1b ; 向后跳转到最近的1:
2: ; 另一个数字标签 nop jnb P1.1, 2f ; 向前跳转到下一个2:
; 示例:循环中使用 mov R7, #101$: ; 带$的数字标签(推荐) djnz R7, 1$ ; 向后跳转
; 嵌套循环 mov R6, #52$: mov R7, #101$: djnz R7, 1$ djnz R6, 2$十、完整示例
; ============================================; STC8G 汇编程序示例; ============================================
; 包含头文件.include "stc8g.inc"
; 常量定义.equ BUFFER_SIZE, 256.equ LED_PIN, P1_0.equ BUTTON_PIN, P3_2.set TIMEOUT, 1000
; 宏定义.macro DELAY_US us .if \us > 0 mov R7, #((\us * 2) & 0xFF) 1$: djnz R7, 1$ .endif.endm
.macro LED_ON setb LED_PIN.endm
.macro LED_OFF clr LED_PIN.endm
.macro TOGGLE_LED cpl LED_PIN.endm
; 位定义.area BSEG (BIT)button_flag: .dbits 1 ; 按键标志tx_busy: .dbits 1 ; 发送忙标志rx_ready: .dbits 1 ; 接收就绪标志
; 数据段.area DSEG (DATA)counter: .byte 0buffer: .ds BUFFER_SIZEtx_index: .byte 0rx_index: .byte 0
; 绝对地址段(中断向量).area VEC (ABS).org 0x0000 ljmp _main ; 复位向量
.org 0x0003 ljmp ext0_isr ; INT0中断
.org 0x000B ljmp timer0_isr ; Timer0中断
.org 0x0023 ljmp uart_isr ; UART中断
; 代码段.area CSEG (CODE)
; ============================================; 主程序; ============================================.globl _main_main:: ; 初始化堆栈 mov SP, #0x80
; 初始化端口 mov P1M0, #0x01 ; P1.0推挽输出 mov P1M1, #0x00
; 初始化定时器 call timer0_init
; 初始化串口 call uart_init
; 使能中断 setb EA setb EX0 ; 使能INT0 setb ET0 ; 使能Timer0 setb ES ; 使能串口中断
; 主循环main_loop: ; 检查按键 jnb button_flag, no_button clr button_flag
; 按键处理 TOGGLE_LED call send_message
no_button: ; 检查接收数据 jnb rx_ready, main_loop clr rx_ready
; 处理接收数据 call process_data
sjmp main_loop
; ============================================; 延时函数(毫秒); 使用宏实现; ============================================.macro DELAY_MS ms push ACC push PSW mov A, #\ms call delay_ms_func pop PSW pop ACC.endm
; 实际的延时函数delay_ms_func: mov R6, A1$: mov R7, #2002$: mov R8, #2503$: djnz R8, 3$ djnz R7, 2$ djnz R6, 1$ ret
; ============================================; 中断服务函数; ============================================ext0_isr:: push PSW push ACC
; 防抖延时 DELAY_US 100
; 设置按键标志 setb button_flag
pop ACC pop PSW reti
timer0_isr:: push PSW push ACC
; 定时器处理 inc counter
; 1秒闪烁 mov A, counter anl A, #0x80 jz timer_done TOGGLE_LED
timer_done: pop ACC pop PSW reti
uart_isr:: push PSW push ACC
; 串口中断处理 jnb RI, uart_tx_check clr RI
; 接收数据 mov A, SBUF call store_rx_data
uart_tx_check: jnb TI, uart_done clr TI setb tx_busy ; 发送完成
uart_done: pop ACC pop PSW reti
; ============================================; 子函数; ============================================; 初始化定时器0timer0_init:: mov TMOD, #0x01 ; 定时器0模式1 mov TH0, #0xFC ; 1ms定时 mov TL0, #0x66 setb TR0 ; 启动定时器 ret
; 初始化串口uart_init:: mov SCON, #0x50 ; 模式1,允许接收 mov PCON, #0x80 ; 波特率加倍 mov TH1, #0xFD ; 9600 bps @11.0592MHz mov TL1, #0xFD setb TR1 ; 启动定时器1 ret
; 存储接收数据store_rx_data: push PSW mov PSW, #0x10 ; 使用第2组寄存器
mov R0, rx_index mov @R0, A ; 存储数据 inc rx_index
; 设置接收就绪标志 setb rx_ready
pop PSW ret
; 发送消息send_message:: mov DPTR, #welcome_msg call send_string ret
; 发送字符串send_string: push ACC1$: clr A movc A, @A+DPTR jz send_done call send_char inc DPTR sjmp 1$send_done: pop ACC ret
; 发送单个字符send_char: jnb tx_busy, $ ; 等待发送完成 clr tx_busy mov SBUF, A ret
; 处理数据process_data:: ; 处理接收缓冲区数据 ret
; ============================================; 常量数据; ============================================welcome_msg: .asciz "STC8G Ready!\r\n"
; ============================================; 程序结束; ============================================ .end十一、编译与链接
1. 编译命令
# 编译汇编文件sdcc -c -mmcs51 --model-small example.asm
# 编译C文件(含内联汇编)sdcc -c -mmcs51 --model-small main.c
# 链接目标文件sdcc -mmcs51 --model-small example.rel main.rel
# 生成Intel HEX文件packihx example.ihx > example.hex2. Makefile示例
TARGET = exampleSRCS = main.asm uart.asm timer.asmOBJS = $(SRCS:.asm=.rel)
CC = sdccCFLAGS = -mmcs51 --model-small --opt-code-size
all: $(TARGET).hex
$(TARGET).hex: $(OBJS) $(CC) $(CFLAGS) $(OBJS) -o $(TARGET).ihx packihx $(TARGET).ihx > $(TARGET).hex
%.rel: %.asm $(CC) -c $(CFLAGS) $<
clean: rm -f *.rel *.asm *.lst *.sym *.ihx *.hex *.map十二、注意事项
- 大小写敏感:SDCC汇编器是大小写敏感的
- 下划线规则:C函数在汇编中前加下划线(如
_main) - 参数传递:通过寄存器R5-R7传递参数
- 返回值:8位在A中,16位在DPL/DPH中
- 内存模型:使用
--model-small、--model-medium、--model-large指定 - 优化选项:使用
--opt-code-size或--opt-code-speed - 调试信息:使用
--debug生成调试信息
评论列表
以下是可爱的评论们:
暂无评论, 呜呜, 快来评论喵!

输入用户名和邮箱后自动检查登录状态。登录后用户名和邮箱将被绑定, 只可以修改头像和主页链接。