elf文件全称是Executable and Linkable Format,可执行连接格式,elf文件中除了机器码以外,还有段加载地址,运行入口地址,数据段等。html
elf文件格式主要有如下三种:ide
elf文件详解:函数
http://www.javashuo.com/article/p-unwgtgag-z.html工具
https://blog.csdn.net/afterlake/article/details/53648912ui
咱们用riscv工具链获得hello.c程序的汇编代码以下,对于rv32和rv64 gcc,编译出来的汇编是不同的。spa
riscv64-unknown-elf-gcc-8.3.0 hello.c -S -o hello.s .file "hello.c" .option nopic .text .section .rodata .align 3 .LC0: .string "Hello World!" .text .align 1 .globl main .type main, @function main: addi sp,sp,-16 sd ra,8(sp) sd s0,0(sp) addi s0,sp,16 lui a5,%hi(.LC0) addi a0,a5,%lo(.LC0) call puts li a5,0 mv a0,a5 ld ra,8(sp) ld s0,0(sp) addi sp,sp,16 jr ra .size main, .-main .ident "GCC: (GNU) 8.3.0" ~
riscv32-unknown-elf-gcc hello.c -S -o hello1.s .file "hello.c" .option nopic .text .section .rodata .align 2 .LC0: .string "Hello World!" .text .align 1 .globl main .type main, @function main: addi sp,sp,-16 sw ra,12(sp) sw s0,8(sp) addi s0,sp,16 lui a5,%hi(.LC0) addi a0,a5,%lo(.LC0) call puts li a5,0 mv a0,a5 lw ra,12(sp) lw s0,8(sp) addi sp,sp,16 jr ra .size main, .-main .ident "GCC: (GNU) 8.3.0"
RV32I 为程序和数据分配内存。图中的顶部是高地址,底部是低地址。在 RISC-V 软件规范中,栈指针(sp)从 0xbffffff0 开始向下增加;程序代码段从 0x00010000 开始,包括静态连接库;程序代码段结束后是静态数据区,在这个例子中假设从 0x10000000 开始;而后是动态数据区,由 C 语言中的alloc()函数分配,向上增加,其中包含动态连接库。.net
.file "hello.c"
.option nopic
.text
.section .rodata
.align 2 //4字节对齐
.LC0:
.string "Hello World!"
.text
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-16 //sp=x2, 调整栈指针,分配栈栈
sw ra,12(sp) //保存函数返回地址,就是main函数的入口地址
sw s0,8(sp) //s0=x8,保存s0,帧指针
addi s0,sp,16 //s0=栈顶地址
lui a5,%hi(.LC0) //计算LC0的地址,a0,…a7保存函数参数地址
addi a0,a5,%lo(.LC0)
call puts //调用puts函数,输出hello world
li a5,0 //读取当即数,a5=0
mv a0,a5 //a0=0,恢复参数地址为0
lw ra,12(sp) //恢复返回地址
lw s0,8(sp) //恢复s0,帧指针
addi sp,sp,16 //恢复sp
jr ra // 跳转到ra地址
.size main, .-main
.ident "GCC: (GNU) 8.3.0"指针