当前位置: 首页 > news >正文

RISCV AS汇编器

文章目录

    • 1. 编译流程
    • 2. 可执行文件
      • 2.1 可重定位目标文件与可执行目标文件
    • 3. 汇编语法
      • 3.1 注释
      • 3.2 标签和符号
      • 3.3 指令伪指令
        • 3.3.1 对齐伪指令
        • 3.3.2 数据定义伪指令
        • 3.3.3 函数相关伪指令
        • 3.3.4 与段相关的伪指令
        • 3.3.5 宏
        • 3.3.6 文件相关的伪指令
    • 4. RISCV 汇编编译选项

1. 编译流程

通常情况下,编译器编译一个可执行文件包含以下几个步骤:

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

输入层

gcc -E

gcc -S

gcc -c

gcc -o

阶段4: 链接 (Linker)

合并多个 .o 文件

解析符号引用
跨文件函数调用

链接标准库
libc / libm / libstdc++

链接启动代码
crt0 / crt1

地址重定位
分配最终内存地址

输出: 可执行文件
ELF / PE / Mach-O

阶段3: 汇编 (Assembler)

汇编指令 → 机器码
二进制操作码

生成符号表
函数/变量地址映射

生成重定位信息
未解析的外部引用

输出: 目标文件
*.o / *.obj

阶段2: 编译 (Compiler Proper)

词法分析
Token化

语法分析
生成 AST/GENERIC

语义分析
类型检查

中间表示转换
GENERIC → GIMPLE → RTL

优化 Pass
SSA、内联、循环优化等

代码生成
输出汇编指令

输出: 汇编代码
*.s 文件

阶段1: 预处理 (Preprocessor)

处理 #include
头文件展开

处理 #define
宏替换

条件编译 #ifdef
选择性保留代码

删除注释
添加行号标记

输出: 纯净C代码
*.i 文件

源代码文件
*.c / *.cpp / *.h

2. 可执行文件

可执行与可链接格式(Executable and Linkable Format, ELF),一种文件格式

常见的段:

  • 代码段(.text):存放程序的可执行机器指令(编译后的二进制代码)。
  • 只读数据段(.rodata):存放只读常量数据。
  • 数据段(.data):存放已初始化的全局变量和静态变量。
  • BSS段(.bss):存放未初始化或初始化为 0 的全局/静态变量。
  • 符号段(.symtab):记录程序中的符号信息(函数名、变量名及其地址)。
  • 可重定位代码段(.rel.text):记录代码中需要重定位的位置。
  • 可重定位数据段(.rel.data):记录数据段中需要重定位的位置。
  • 调试符号段(.debug):存放调试信息,供 GDB 等调试器使用。

2.1 可重定位目标文件与可执行目标文件

可重定位目标文件:在链接阶段和其他可重定位目标文件合并成一个可执行文件

  • 包含代码和数据
  • 所有段的起始地址不确定,用0填充
  • 可重定位代码段(.rel.text)
  • 可重定位数据段(.rel.data)

可执行目标文件:可以执行的目标文件

  • 包含代码和数据
  • 所有段的起始地址都已经确定

3. 汇编语法

3.1 注释

在.S文件中支持三种注释:

  • “//” 单行注释
  • “#” 在一行开始表示注释整行
  • “/**/” 多行注释

注: .S文件会经过预处理器处理,可以使用C语言中的注释方式,经过预处理以后会被丢弃,.s文件中只能用汇编注释#。

3.2 标签和符号

  • 标签 (Label):后面紧跟冒号 :,代表所在位置的地址。常用于跳转或函数入口。start: 或 loop_start: 都是标签。
  • 符号 (Symbol):指代一段数据或代码的名字,但不一定需要紧跟冒号。通过 .equ、.set、#define(仅 .S)定义的常量,或用 .globl 导出的函数名,都是符号。
label_name: # 普通标签(冒号结尾) instruction 1: # 局部标签(纯数字,用于临时跳转) instruction jmp 1f # 1f = 向前(forward)找下一个 "1:" jmp 1b # 1b = 向后(backward)找上一个 "1:"
类型示例说明
全局符号main:_start:默认局部可见,需.global导出
局部符号main:_start:默认局部可见,通常用.local声明
局部标签1:2:临时标记,配合f/b使用
符号赋值symbol = 0x1000等价于常量,不占内存
等值伪指令.set name, 0x100定义符号常量

符号代表所在的地址,也可以当作变量或者函数来使用,符号由字母,数字,‘_’ 和’.'和"$"组成。

局部标签不一定是符号(数字标签就不是),局部符号一定是符号表中的条目。

3.3 指令伪指令

指令是真正的机器指令,汇编后直接生成对应的机器码,并且寄存器必须小写,指令可以是全大写或者全小写。

[前缀] 操作码 [源操作数], [目的操作数]

伪指令以点 . 开头,是汇编器的命令,不生成机器码,控制汇编过程。
伪指令可以实现如下功能:

  • 符号定义
  • 数据定义和对齐
  • 汇编控制
  • 汇编宏
  • 段描述
3.3.1 对齐伪指令
  1. .align 对齐,填充数据来实现对齐,可以填入0或者nop指令
  2. 告诉汇编器,.align 后面的汇编必须从下一个能被2^n整除的地址开始分配
  3. RISCV中第一个参数表示2^n大小
.align expression [, fill_value [, max_bytes]]
参数说明默认值
expression对齐边界(含义因架构而异)必需
fill_value填充字节值0(x86)/ 0x00 或 nop(其他)
max_bytes最大填充字节数,超过则跳过对齐无限制
3.3.2 数据定义伪指令

基本数据定义伪指令:

伪指令数据大小说明示例
.byte8-bit (1 字节)定义字节.byte 0xFF, -1, 'A'
.short/.hword16-bit (2 字节)定义半字.short 0x1234, -300
.long/.int/.word32-bit (4 字节)定义字.long 0x12345678
.quad64-bit (8 字节)定义四字.quad 0x123456789ABCDEF0
.octa128-bit (16 字节)定义八字.octa 0x...
.single/.float32-bit单精度浮点.float 3.14, -0.5
.double64-bit双精度浮点.double 3.1415926535

字符串定义伪指令:

伪指令自动补\0说明示例
.ascii❌ 否ASCII 字符串(原始).ascii "Hello"
.asciz✅ 是ASCII + 自动补零.asciz "Hello"
.string✅ 是.asciz.string "Hello"
.string8✅ 是8-bit 字符.string8 "Hello"
.string16✅ 是16-bit 宽字符.string16 "Hello"
.string32✅ 是32-bit 宽字符.string32 "Hello"
3.3.3 函数相关伪指令

.global定义一个全局符号
.include引用头文件
.if,.else,.endif控制语句

3.3.4 与段相关的伪指令
  1. .section
.section name,"flags"

.section: 表示接下来的数据或者指令会链接到哪个段中,每一个段以段名为开始,以下一个段名或者文件末尾为结束。

字符全称含义ELF 段头标志
aAllocatable段在运行时分配内存SHF_ALLOC
eExclude链接时排除该段SHF_EXCLUDE
wWritable段内容可写SHF_WRITE
xExecutable段内容可执行SHF_EXECINSTR
MMergeable相同内容段可合并SHF_MERGE
SStrings段包含null 结尾字符串SHF_STRINGS
GGroup段属于COMDAT 组SHF_GROUP
TTLS线程局部存储SHF_TLS
?保留未知/保留标志
  1. .pushsection.popsection
.pushsection name, "flags", @type # ... 在新段中定义内容 ... .popsection
伪指令作用
.pushsection保存当前段上下文,切换到指定新段
.popsection恢复之前保存的段上下文
  1. .section.previous
初始状态: 当前在 .text 段 .section .data, "aw", @progbits ──► 切换到 .data 记住: 上一个段是 .text [在 .data 中定义数据] .previous ──► 回到 .text(上一个段) [继续在 .text 写代码] .section .rodata, "a", @progbits ──► 切换到 .rodata 记住: 上一个段是 .text(.previous 后的当前段) [定义只读数据] .previous ──► 回到 .text
特性.section+.previous.pushsection+.popsection
记忆层数仅一层(上一个段)多层栈(支持嵌套)
切换方式直接切换,覆盖记忆压栈保存,精确恢复
嵌套支持❌ 不支持嵌套(会丢失更早的段)✅ 支持任意深度嵌套
适用场景简单两段切换复杂多段嵌套、编译器生成
安全性容易误用(忘记当前段)栈结构,成对使用更安全
3.3.5 宏
  1. 汇编中的宏通过.macro.endm定义
  2. .macro后面是宏的名称,然后是跟宏的参数
  3. 在宏里面使用参数要加“\”
.macro add_1 p1 p2 add x0, \p1, \p2 .endm
  1. 宏定义的时候可以设置一个初始值:
.macro reserve_str p0=0,p2 .endm # 由于第一个参数有一个默认值,可以省略默认值 reserve_str ,b reserve_str a,b
  1. 宏参数后面加.req表示在宏调用过程中必须传递一个值,否则会编译出错
3.3.6 文件相关的伪指令

.incbin 伪指令可以把文件的二进制数据嵌入到当前位置。
.include 伪指令可以把汇编代码插入到当前指令所在位置。

4. RISCV 汇编编译选项

选项作用常用值
-fpic/-fPIC位置无关代码(共享库)-fPIC(大模型)
-fno-pic绝对地址代码(裸机/静态)默认裸机
-mabi=整数/浮点/指针宽度lp64d,ilp32
-march=指令集扩展rv64gc,rv32imac
-misa-spec=ISA 规范版本20191213
-mlittle-endian小端存储(默认)-
-mbig-endian大端存储-
http://www.jsqmd.com/news/842457/

相关文章:

  • 不止于连接:华为云IoT设备上线后,用MQTT.fx玩转属性上报与命令下发
  • 语义搜索实战:把向量检索和实时SERP结合起来做问答系统
  • Linux故障时间线复盘排查方法
  • NotebookLM知识图谱构建,错过这48小时将丧失首批Agent-native知识中枢接入资格
  • Cursor Pro终极破解教程:三步免费解锁AI编程助手完整指南
  • 奇异非混沌动力学导向的智能控制方法在纸张横向定量控制中的应用设计【附代码】
  • 2025届必备的五大AI学术方案实测分析
  • React时间范围选择器实战:openstatusHQ/time-picker组件深度解析与应用
  • Graph-CoT:图神经网络与思维链融合的复杂推理技术实践
  • 本地部署dify的Excel提取器出现以下问题:Error extracting from Excel workbook: Request URL is missing an ‘http://’ or
  • Floquet量子码的动态纠错与时空同步技术解析
  • 【NotebookLM审稿回复黄金模板】:20年学术AI工具实战专家亲授3类高拒稿率意见的5步逆转法
  • VSCode时间追踪插件开发指南:从零构建本地化专注力工具
  • K8s 之 ingress
  • npmmirror 镜像站:从淘宝npm到独立域名,国内开发者的高效npm加速方案
  • 量子纠错与Floquet码:动态编码与ZX演算实践
  • 自适应光学在双光子贝塞尔光片荧光显微镜中的应用【附代码】
  • 别再让GPT瞎猜了!用LangChain的Chain of Thought,手把手教你构建‘会思考’的水果推荐助手
  • 别再手动算q值了!用Excel地理探测器软件包,5分钟搞定空间分异分析
  • 2026年实测10款免费降AI率神器:从降AI到AIGC免费降重,可至5%以下 - 降AI实验室
  • NotebookLM审稿回复效率提升300%:用结构化Prompt工程重构Response框架(含可直接导入的Notion模板)
  • 星地激光通信系统调制格式识别技术【附代码】
  • AgentBox:基于容器化与Cascade协议的多AI智能体协作平台架构与实践
  • 对比自行维护多个 API 密钥,使用 Taotoken 在管理上轻松许多
  • 腾讯音乐完成并购喜马拉雅:后者作价20亿美元 IPO之路坎坷终“卖身”
  • 基于强化学习的DRAM内存控制器优化框架ReLMXEL
  • Flutter技能仪表盘:量化学习路径与可视化成长管理
  • NotebookLM能源知识图谱构建全链路(从PDF文献到可推理决策引擎)
  • 大模型风口已至!月薪30K+的AI岗正在批量诞生,这份学习路线助你从零基础到精通!
  • SFT与RL:AI训练的黄金搭档,何时介入才能事半功倍?