开发者生态
morning
Riscrithm – 用 Go 编码的直观 RISC-V 汇编器和优化器
2026-05-25
1 阅读
patrick-ghetea
Riscrithm 开发人员手册 嘿,那里。如果您正在查看此内容,您可能正在接触 Riscrithm,这是一种高级宏汇编语言,可直接编译为纯 RISC-V 汇编。将其视为高级语言的可读性与裸机硬件的原始确定性控制之间的桥梁。让我们直接深入了解编译器的工作原理、语法规则以及幕后发生的事情。 1. CLI 要编译源代码,您将使用 riscrithm CLI 工具。语法很简单: riscrithm " source_code_file " " assembly_target_file " [-o/--optimize] 源代码:您的 Riscrithm 输入文件。目标文件:生成的.s汇编文件。如果该文件不存在,编译器将即时为您创建它。优化:传递 -o 或 --optimize 来启用优化扫描(稍后将详细介绍编译器架构)。 2. 文件结构和全局 每个 Riscrithm 文件必须在最顶部声明其目标部分和入口点。这些行和宏定义是唯一允许在标签块外部完全不缩进存在的行。标头和入口点标头:设置装配部分。例如,标头默认转换为 .section .text。入口点:定义程序开始的位置。传递入口点 main 会转换为 .globl main。 headerdefaultentrypointmain 定义(宏) 您可以使用define关键字定义文本替换宏。这非常适合别名寄存器或创建单行内联函数。以下是一些经典的开发示例:define foo = x1、define bar = x2、define baz = x3、define horseBattery = x4、define apple = 10、define Orange = 20、define clearFoo = foo ^^ 每当解析器看到 foo 时,它都会在处理任何实际逻辑之前将其与 x1 交换。注释 注释是使用# 符号编写的。编译器会删除任何行上 # 后面的任何内容,因此您可以将它们安全地放置在任何位置。 3. 标签、缩进和原始块 Riscrithm 通过缩进严格限定范围。标准标签 标签定义您的执行块,并且必须以冒号结尾。它们不得有任何缩进。相反,标签内的每条指令都必须缩进(空格或制表符)。如果指令不缩进,编译器将抛出语法错误。 main: load foo = apple move bar = foo 原始汇编标签 (!!) 如果您需要绕过 Riscrithm 预处理器并编写原始 RISC-V 汇编,请在标签前加上 !!。编译器会去掉感叹号,但会完全不受影响地传递该块内的所有内容。宏和简写这里就不展开了。 !!raw_block: li x1, 10 foo ^^ # 这与所写的完全一样! 4. 核心特性和说明 这是该语言的核心内容。 Riscrithm 将可读语句直接映射到硬件指令。系统和中断控制 不用记住特权级操作码,而是使用显式系统调用: Riscrithm RISC-V 汇编描述 Interrupt.u uret 用户模式陷阱返回中断.sret 超级用户模式陷阱返回 Interrupt.m mret 机器模式陷阱返回 wait wfi 等待中断(低功耗状态) trap ebreak 调试器陷阱 stop ecall 系统环境调用 /halt ... nop 无操作(省略号) 5. 命名约定 让我们来谈谈代码风格。为了保持 Riscrithm 源文件的可读性和一致性,编译器期望(并且强烈鼓励)对标识符的命名方式进行清晰的划分。以下是命名约定细分: 变量和寄存器(驼峰命名法):您定义的任何变量别名或寄存器宏都应以小写字母开头,每个后续单词大写。示例:firstNum、addressRegister、stackOffset 标签和代码块 (snake_case):执行目标、循环边界和条件块使用以下划线分隔的小写单词。这使得它们在视觉上与指示相反。示例:loop_start、on_true、error_handler 常量和文字 (SCREAMING_SNAKE_CASE):不应更改的硬编码配置值、静态偏移量或全局定义,使用下划线分隔的全大写字母。示例:DEFAULT_HEADER、MAX_BUFFER_SIZE、IMM_VALUE 6. 完整运算符和表达式参考 除了硬件系统陷阱和条件分支符号之外,这里是单遍编译器引擎支持的变元、算术表达式和内存运算符的完整表。核心表达式和内存运算符 Riscrithm 语法类别 内部扩展/行为目标 RISC-V 汇编 load = 赋值 直接立即赋值 li reg, imm move = 赋值 寄存器到寄存器复制 mv reg1, reg2 swap 值交换 Triple-XOR 非破坏性交换 xor reg1, reg1, reg2 xor reg2, reg1, reg2 xor reg1, reg1, reg2 -> stack.[b/w/d] 堆栈内存 Dec 指针,存储字节/字/double addi sp, sp, -offset s[b/w/d] reg, 0(sp) <- stack.[b/w/d] 堆栈内存加载 byte/word/double,inc 指针 l[b/w/d] reg, 0(sp) addi sp, sp, offset = stack.[