RVOS练习4-1

编写一个简单的打印 “hello world!” 的程序源文件:hello.c

1
2
3
4
5
6
#include <stdio.h>

void main()
{
printf("hello world!");
}

对源文件进行编译,生成针对支持 rv32ima 指令集架构处理器的目标文件 hello.o

使用指令riscv64-unknown-elf-gcc -march=rv32ima -mabi=ilp32 -c hello.c进行编译出现以下错误

1
2
3
4
hello.c:1:10: fatal error: stdio.h: No such file or directory
1 | #include <stdio.h>
| ^~~~~~~~~
compilation terminated.

该错误在errata.pdf中和gitee的issue有提及,根据errata.pdf,将gcc更换为riscv64-linux-gnu-gcc,使用指令riscv64-linux-gnu-gcc -march=rv32ima -mabi=ilp32 -c hello.c进行编译,仍出现报错,报错为

1
2
3
4
5
6
7
8
In file included from /usr/riscv64-linux-gnu/include/features.h:510,
from /usr/riscv64-linux-gnu/include/bits/libc-header-start.h:33,
from /usr/riscv64-linux-gnu/include/stdio.h:27,
from hello.c:1:
/usr/riscv64-linux-gnu/include/gnu/stubs.h:8:11: fatal error: gnu/stubs-ilp32.h: No such file or directory
8 | # include <gnu/stubs-ilp32.h>
| ^~~~~~~~~~~~~~~~~~~
compilation terminated.

之后再issue下的讨论找到方法,只需要去除-march-mabi选项即可.

查看 hello.o 的文件的文件头信息

使用指令readelf -h hello.o查看文件头信息,输出如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: RISC-V
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 840 (bytes into file)
Flags: 0x5, RVC, double-float ABI
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 12
Section header string table index: 11

查看 hello.o 的 Section header table

使用指令readelf -SW hello.o查看Section header table,输出如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
There are 12 section headers, starting at offset 0x348:

Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 000022 00 AX 0 0 2
[ 2] .rela.text RELA 0000000000000000 000250 000090 18 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 000062 000000 00 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 000062 000000 00 WA 0 0 1
[ 5] .rodata PROGBITS 0000000000000000 000068 00000d 00 A 0 0 8
[ 6] .comment PROGBITS 0000000000000000 000075 00002c 01 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 0000a1 000000 00 0 0 1
[ 8] .riscv.attributes RISCV_ATTRIBUTES 0000000000000000 0000a1 000033 00 0 0 1
[ 9] .symtab SYMTAB 0000000000000000 0000d8 000150 18 10 12 8
[10] .strtab STRTAB 0000000000000000 000228 000022 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0002e0 000064 00 0 0 1

对 hello.o 反汇编,并查看 hello.c 的 C 程序源码和机器指令的对应关系

使用riscv64-linux-gnu-objdump -S hello.o查看反汇编后的代码,输出如下

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
hello.o:     file format elf64-littleriscv


Disassembly of section .text:

0000000000000000 <main>:
#include <stdio.h>

void main()
{
0: 1141 addi sp,sp,-16
2: e406 sd ra,8(sp)
4: e022 sd s0,0(sp)
6: 0800 addi s0,sp,16
printf("hello world!");
8: 00000517 auipc a0,0x0
c: 00050513 mv a0,a0
10: 00000097 auipc ra,0x0
14: 000080e7 jalr ra # 10 <main+0x10>
}
18: 0001 nop
1a: 60a2 ld ra,8(sp)
1c: 6402 ld s0,0(sp)
1e: 0141 addi sp,sp,16
20: 8082 ret