程序加载及执行

本文将针对RISC-V的加载和执行流程进行介绍。

elf分段

加载

RISCV程序执行流程

初始化代码

RISCV程序执行前需要一段初始化代码,执行硬件、内存初始化、设置堆栈指针等操作,初始化代码为start.S:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.section .init
.globl _start
.globl _end
.type _start, @function

_start:
/* Clear general purpose registers */
mv x1, x0
mv x2, x0
...

.option push
.option norelax
la gp, __global_pointer$ // 设置全局指针寄存器,指向global data (x3)
.option pop
la sp, __sp_start // 设置堆栈起始地址(x2)

la a0, _default_handler // 设置default exception handler, 如果未指定异常处理流程,就会
csrw mtvec, a0 // 跳转至此处

/* Load text section */
la a0, __text_lma_start // load memory addr (物理地址)
la a1, __text_vma_start // virtual memory addr
la a2, __text_vma_end // virtual memory end
bgeu a1, a2, 2f // start >= end? maybe start from ROM

/* 下面这段代码进行了一个简单的内存搬运,
将从lma开始的text完全搬运至vma开始的地址。
不过此处lma和vma地址相同 */
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
call _startFromROM

程序接下来会跳转至startROM.S中的_startFromROM继续执行,并逐步跳转至main函数,_startFromROM位于text段内,主要会做一下段拷贝工作,然后跳转至vv_main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    .section .text
.globl _startFromROM
.type _startFromROM,@function

_startFromROM:

/* Load rodata section */
la a0, __rodata_lma_start
la a1, __rodata_vma_start
la a2, __rodata_vma_end
bgeu a1, a2, skip_rodata
loop_rodata:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, loop_rodata
skip_rodata:

/* Load "init_n_xtors" section */
/* Load data section */
/* Clear bss section */

/* argc = argv = 0 */
li a0, 0
li a1, 0
call vv_main

0%