elf文件全稱是Executable and Linkable Format,可執行鏈接格式,elf文件中除了機器碼之外,還有段加載地址,運行入口地址,數據段等。
elf文件格式主要有以下三種:
- 可重定向文件:文件保存着代碼和適當的數據,用來和其它的目標文件一起來創建一個可執行文件或者共享目標文件。
- 可執行文件:文件保存着一個用來執行的文件。
- 共享目標文件:即共享庫。
elf文件詳解:
https://www.cnblogs.com/gatsby123/p/9750187.html
https://blog.csdn.net/afterlake/article/details/53648912
我們用riscv工具鏈得到hello.c程序的匯編代碼如下,對於rv32和rv64 gcc,編譯出來的匯編是不一樣的。
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()函數分配,向上增長,其中包含動態鏈接庫。
.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"