Skip to content

Latest commit

 

History

History
32 lines (24 loc) · 1.66 KB

20220421-riscv-la.md

File metadata and controls

32 lines (24 loc) · 1.66 KB

RISC-V la 伪指令的理解

Pseudoinstruction Base Instruction(s) Meaning Comment
la rd, symbol auipc rd, symbol[31:12]; addi rd, rd, symbol[11:0] Load address With .option nopic (Default)
la rd, symbol auipc rd, symbol@GOT[31:12]; l{w|d} rd, symbol@GOT[11:0](rd) Load address With .option pic

la 加载的指令地址是相对的(大约所有用到符号地址的伪指令,地址都是相对的)。或者说,编译这类指令时,会假设一个当前的 pc,然后根据当前 pc 推算目标符号的位置。因此,如果程序加载到不是链接脚本指定的位置,或启用虚存,将 pc 搬移到另一个位置,符号表产生的位置都会随之改变,相对的才是不变的。

extern "C" {
    fn symbol();
}

就是符号表在 rust 里的表示。symbol 的值和 la 加载出来的一样。


使用这个过程跳到高处的虚存:

# 从地址空间的低处跳到地址空间高处对应位置并挪动栈指针
# -------------------------------
_jump_higher:                # fn jump_heigher(offset: usize) {{
    add  ra, ra, a0          #     $t0 += offset;
    add  sp, sp, a0          #     $sp += offset;
    ret                      # }}
# -------------------------------

但是必须注意,寄存器里存放的所有地址也要跟着一起跳。本质上说,内核映射到高地址是为了给用户让出空间,所以跳后直接解除对跳板页的映射也得应该正确的,一切对跳板页上地址的映射都必须释放,或者跟着 pc 鸡犬升天。这里跟着跳了栈指针。