CS61C学习笔记(五)-RISCV-CALL
CALL
Compiling,Assembling, Linking, and Loading
伪代码
给汇编理解的,而不是给机器了解的
答案:
翻译和运行项目:CALL
接下来我们将讨论怎么将高级语言翻译成机器码
我们怎么运行C程序?
**翻译器(Translator)**:将程序从源语言转换为另一种语言中的等效程序
- 翻译/编译成低级语言几乎总是意味着更高的效率和更高的性能。
与**解释器(Interpreter)**对比:直接在源语言中执行程序
- ▫注意:C 程序/RISC-V 也可以被解释执行! ▫
- 例如:Venus RISC-V 模拟器 对于学习/调试非常有用
编译和运行一个C项目的步骤
CALL: Compiler
CALL: Assembler
directives: 指令
指令(directives)
指令 向汇编器提供指示:
通常由编译器生成(上一个阶段)
指令不会生成机器指令!相反,它们指示如何构建目标文件的不同部分。
.text
随后的项放入用户文本段(机器代码).data
随后的项放入用户数据段(源文件数据的二进制形式).globl sym
声明符号为全局符号,可以从其他文件中引用.string str
将字符串存储在内存中,并以空字符结尾.word w1 … wn
存储 n 个 32 位数量在连续的内存字中
Object File Format
Object File Heade
r : size and position of other pieces of the object fileText Segment
: machine codeData Segment
: binary representation of static data in the source fileSymbol Table
: LIst of file’s labels, static data that can be referenced by other programsRelocation Information
: Lines of code to fix later(by Linker)Debugging Information
生成机器码
简单情况
- 算术、逻辑、移位等
- 所有必要的信息已经包含在指令中
例如:
add x18, x18, x10 addi x19, x19, -1
PC相对分支和跳转:
- 例如,``beq
,
bne等,以及
jal` - 位置无关代码(PIC):
- 一旦伪指令被实际指令替换,所有PC相对寻址都可以计算出来
例如:
j Label
jal x0, Label
- 通过计算当前指令和目标指令之间的半字指令数量来确定编码的偏移量
计算PC相对地址(Program Counter-relative addresses):两次循环
1. 前向引用(Forward Reference)问题
在程序中,分支指令和PC相对跳转指令可能引用在程序中后面(“前向”)的标签。例如,跳转指令j Loop
在程序中会跳到Loop
标签处。但是在第一次扫描时,Loop
标签的位置还不确定,因此无法准确计算跳转所需的偏移量。
2. 偏移量的精确计算
因为在第一次扫描时,程序中的某些标签的位置还不知道,所以无法计算出精确的正偏移量。在第二次扫描时,所有标签的位置都已知,可以根据这些已知位置计算出精确的偏移量。
具体的两次扫描过程
- 第一次扫描:记录标签的位置(存储在符号表中)。
- 在第一次扫描过程中,程序遍历所有指令,并记录每个标签的位置(即地址)。这个过程无需计算具体的偏移量,只需确保所有标签的位置都记录下来。
- 第二次扫描:使用标签位置生成机器代码。
- 在第二次扫描过程中,程序使用第一次扫描中记录的标签位置来计算每个分支指令和跳转指令所需的精确偏移量。然后,生成最终的机器代码。
通过这样的两次扫描,可以解决前向引用问题,并确保所有偏移量都准确无误。正如图中所示:
- 跳转到
Loop
标签需要往前跳3个字(offset -6)。 - 跳转到
Exit
标签需要往后跳3个字(offset +6)。
这就是为什么需要两个循环才能正确翻译计算机程序中的PC相对地址。
那其他引用呢?
- 引用其他文件?
- 例如,从 C 字符串库调用
strlen
- 例如,从 C 字符串库调用
- 引用静态数据?
- 例如,
la
被分解为lui
和addi
- 这些需要知道数据的完整32位地址
- 例如,
- 这些还无法确定,因此汇编器会将它们记录在两个表中:重定位信息表和符号表。
Symbol Table
- List of “items” in this file
- file’s labels, static data
- 指令区-Instruction Labels
- 用来计算
branches, function calling, etc
PC相对地址的机器码 .global
命令:可以被其他文件引用的标签
- 用来计算
Data
: 在.data
片段中的所有- 全局变量可能被其他文件访问/使用
重定向信息(Relocation Information)
- List of “items” whose address this file needs
- Any external label jumped to
- External lable(including lib files):
jal ext_label
- External lable(including lib files):
- Any piece of data in static section
- e.g.,
la
instruction)forlw/sw
base register)
- e.g.,
CALL: Linker
链接器将多个对象模块修补在一起
哪一些地址需要重定向?
哪一些指令需要重定向编辑?
解析引用
Static vs. Dynamic Linking
Dynamically-Linked Libraries(DLLs)
CALL: Loader
例子:Hello, World!
编译器 将单个高级语言文件转换为单个汇编语言文件。
汇编器 删除伪指令,将其能转换的内容转换为机器语言,并为链接器创建检查表(重定位表)。
- 进行两次遍历以解析地址,处理内部前向引用。
链接器 组合多个 .o 文件并解析绝对地址。
- 允许单独编译,不需要编译库,并解析剩余的地址。
加载器 将可执行文件加载到内存中并开始执行。