CALL

Compiling,Assembling, Linking, and Loading

伪代码

给汇编理解的,而不是给机器了解的

image-20240606224755365

答案:

image-20240606224829394

翻译和运行项目:CALL

image-20240606225135064

接下来我们将讨论怎么将高级语言翻译成机器码

我们怎么运行C程序?

  • **翻译器(Translator)**:将程序从源语言转换为另一种语言中的等效程序

    • 翻译/编译成低级语言几乎总是意味着更高的效率和更高的性能。
  • 与**解释器(Interpreter)**对比:直接在源语言中执行程序

    • ▫注意:C 程序/RISC-V 也可以被解释执行! ▫
    • 例如:Venus RISC-V 模拟器 对于学习/调试非常有用

编译和运行一个C项目的步骤

image-20240606225653877

CALL: Compiler

image-20240606225907637

CALL: Assembler

image-20240606225925322

directives: 指令

指令(directives)

  • 指令 向汇编器提供指示:

    • 通常由编译器生成(上一个阶段)

    • 指令不会生成机器指令!相反,它们指示如何构建目标文件的不同部分。

  • .text
    随后的项放入用户文本段(机器代码)

  • .data
    随后的项放入用户数据段(源文件数据的二进制形式)

  • .globl sym
    声明符号为全局符号,可以从其他文件中引用

  • .string str
    将字符串存储在内存中,并以空字符结尾

  • .word w1 … wn
    存储 n 个 32 位数量在连续的内存字中

image-20240606232836195

Object File Format

  • Object File Header : size and position of other pieces of the object file
  • Text Segment : machine code
  • Data Segment : binary representation of static data in the source file
  • Symbol Table: LIst of file’s labels, static data that can be referenced by other programs
  • Relocation Information: Lines of code to fix later(by Linker)
  • Debugging Information

生成机器码

简单情况

  • 算术、逻辑、移位等
  • 所有必要的信息已经包含在指令中

例如:

  • add x18, x18, x10
    addi x19, x19, -1
    

PC相对分支和跳转:

  • 例如,``beqbne等,以及jal`
  • 位置无关代码(PIC):
    • 一旦伪指令被实际指令替换,所有PC相对寻址都可以计算出来

例如:

  • j Label
  • jal x0, Label
  • 通过计算当前指令和目标指令之间的半字指令数量来确定编码的偏移量

image-20240607002511692

计算PC相对地址(Program Counter-relative addresses):两次循环

1. 前向引用(Forward Reference)问题

在程序中,分支指令和PC相对跳转指令可能引用在程序中后面(“前向”)的标签。例如,跳转指令j Loop在程序中会跳到Loop标签处。但是在第一次扫描时,Loop标签的位置还不确定,因此无法准确计算跳转所需的偏移量。

2. 偏移量的精确计算

因为在第一次扫描时,程序中的某些标签的位置还不知道,所以无法计算出精确的正偏移量。在第二次扫描时,所有标签的位置都已知,可以根据这些已知位置计算出精确的偏移量。

具体的两次扫描过程

  1. 第一次扫描:记录标签的位置(存储在符号表中)。
    • 在第一次扫描过程中,程序遍历所有指令,并记录每个标签的位置(即地址)。这个过程无需计算具体的偏移量,只需确保所有标签的位置都记录下来。
  2. 第二次扫描:使用标签位置生成机器代码。
    • 在第二次扫描过程中,程序使用第一次扫描中记录的标签位置来计算每个分支指令和跳转指令所需的精确偏移量。然后,生成最终的机器代码。

通过这样的两次扫描,可以解决前向引用问题,并确保所有偏移量都准确无误。正如图中所示:

  • 跳转到Loop标签需要往前跳3个字(offset -6)。
  • 跳转到Exit标签需要往后跳3个字(offset +6)。

这就是为什么需要两个循环才能正确翻译计算机程序中的PC相对地址。

image-20240607175354375

那其他引用呢?

  • 引用其他文件?
    • 例如,从 C 字符串库调用 strlen
  • 引用静态数据?
    • 例如,la 被分解为 luiaddi
    • 这些需要知道数据的完整32位地址
  • 这些还无法确定,因此汇编器会将它们记录在两个表中:重定位信息表和符号表。

Symbol Table

  • List of “items” in this file
    • file’s labels, static data
  • 指令区-Instruction Labels
    • 用来计算branches, function calling, etcPC相对地址的机器码
    • .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
  • Any piece of data in static section
    • e.g., la instruction)for lw/sw base register)

CALL: Linker

image-20240606234631886

链接器将多个对象模块修补在一起

image-20240607181938505

哪一些地址需要重定向?

image-20240607183427874

哪一些指令需要重定向编辑?

image-20240607183443724

解析引用

image-20240607183653126

image-20240607183701004

Static vs. Dynamic Linking

image-20240607183723584

Dynamically-Linked Libraries(DLLs)

image-20240607183746577

CALL: Loader

image-20240606234925439

image-20240607193732007

image-20240607193750317

例子:Hello, World!

image-20240606235020474

image-20240606235028361

image-20240606235037716

image-20240606235048081

image-20240606235059216

image-20240606235129941

  • 编译器 将单个高级语言文件转换为单个汇编语言文件。

  • 汇编器 删除伪指令,将其能转换的内容转换为机器语言,并为链接器创建检查表(重定位表)。

    • 进行两次遍历以解析地址,处理内部前向引用。
  • 链接器 组合多个 .o 文件并解析绝对地址。

    • 允许单独编译,不需要编译库,并解析剩余的地址。
  • 加载器 将可执行文件加载到内存中并开始执行。

翻译(Translation)和解释(Interpretation)的比较

image-20240606235317698

image-20240606235335502

Interpretation

image-20240606235355009

image-20240606235404823

Interpretation vs. Translation?

image-20240606235433798

image-20240606235439346