RISC-V ISA介绍 | 编译链接 | 嵌入式开发介绍

(资源链接见文末)

RISC-V ISA介绍 

         加州伯克利所研发的第五代精简指令集。

        ISA指令集架构:是底层硬件电路面向上层软件程序提供的一层接口规范。

        ISA(处理器)的宽度指的是CPU中通用寄存器的宽度,这决定了寻址范围的大小,以及数据运算能力。

        ISA的宽度与指令编码长度无关。

        目前主流的移动智能终端,个人计算机和服务器用的寄存器是64位。

命名规范

        RV[###][abc......xyz]

        [###]表示的是寄存器的位宽,后面的字母标识处理器支持的指令集模块集合。

        例如:RV31MA、RV64GC。

特点

        RISC-V每条指令是32位。

        RISC-V是模块化ISA。

        增量式ISA:x86

        模块化ISA:由1个基本整数指令集+多个可选的指令集组成。基础指令是固定的,永远不会改变。设计cpu的可以像插件一样去堆模块。

        RISC-V ISA = 1个基本整数指令集 + 多个可选的扩展指令集

        基本整数指令集:唯一强制要求实现的基础指令集,其他指令集都是可选的扩展模块。

基本指令集描述
RV32I32位整数指令集
RV32ERV32I的子集,用于小型的嵌入式场景
RV64I64位的整数指令集,兼容RV32I
RV128I128位整数指令集,兼容RV64I和RV32I

        扩展模块指令集:RISC-V允许在视线中以可选的形式实现其他标准化和非标准化的指令集扩展。特定组合“IMAFD”被称为“通用”组合,用英文字母G表示。

扩展指令集描述
M整式乘法与除法指令集
A存储器原子指令集
F单精度浮点指令集
D双精度浮点指令集
C压缩指令集
......其它标准化和非标准化指令集

        例子:RV32I:最基本的RISC-V实现;RV32IMAC:32位实现,支持I+M+A+C; RV64GC: 64位实现,支持IMAFDC。

HART

        hart = hardware thread

        英特尔提出的超线程概念,一个处理器处理多个指令流。买回来的处理器说是4核,实际上是两核,每个核可以同时执行两条指令流。

        引入hart概念,一个hart就是一个虚拟的cpu。一个hart可以不受外界干扰的自主地去获取和执行risc-v指令。

特权级别

levelencodingname
000user/applicationU
101supervisorS
210reserved
311machineM

        当运行在用户态时,就是说cpu运行在user级别,进入到内核的时候就是supervisor级别。固件就是就是machine级别。运行在machine模式是不开虚拟地址的,全部运行在物理地址。

        risc-v芯片一上电首先是进入到machine模式,再进入到supervisor模式,此时也叫保护模式,虚拟地址打开。

        进程的实现依赖于虚拟地址,虚拟地址的实现需要MMU硬件支持。

Control and Status Register(CSR)

        不同的特权级别下时分布对应各自的一套CSR,用于控制和获取响应level下的处理器工作状态。

        高级别的特权可以访问低级别的CSR。比如说machine级别可以访问user级别的csr。

        rsicv定义了专门用于操作csr的指令。

        如果是用户程序,不太需要跟csr打交道。

内存管理与保护

        物理内存保护(Physical Memory Protection,PMP):允许M模式指定U模式可以访问的内存地址;支持R/W/X(可执行),以及lock。

        虚拟内存:需要支持supervisor level;用硬件MMU支持实现。

异常和中断

        异常:主动触发,cpu给你一次改过自新的机会,去执行一段挽救程序;当执行到非法指令的时候,cpu会停掉此指令流跳到一个特殊的地址去执行一段特殊的程序(自己写的程序,想对异常做的处理),执行完之后回到之前的指令再次运行;比如说除0异常;

        中断:被动触发;cpu停掉当前程序,跳转到执行中断处理程序,执行完返回到下一条指令去执行;比如说外设通知你发生一件什么事情,跑去执行别的指令,执行完再回到下条指令,就像中断没有发生过一样。

编译与链接

GCC(GNU Compiler Collection)

        由GNU开发的,遵循GPL许可证发行的编译器套件;支持此c、c++、objective-c、fortran、ada和go语言等多种语言前端,已被移植到多种计算机体系架构上,如x86、arm、risc-v等;GCC的初衷是为GNU操作系统专门编写一款编译器,现以被大多数“unix-like”操作系统(如linux、BSD、MacOS)采纳为标准的编译器。

        gcc [options][filenames]

常用选项含义
-E只做预处理
-c值编译不链接,生成目标文件“-.o”
-S生成汇编代码
-o file把输出生成到由file指定文件名的文件中
-g在输出的文件中加入支持调试的信息

-v

显示输出详细的命令执行过程信息
gcc -E foo.c -o foo.i // preprocessor/cc1
gcc -S foo.i -o foo.s // compiler/cc1
gcc -c foo.s -o foo.o // assembler/as
gcc foo.o -o a.out    // linker/ld

        gcc的主要执行步骤:

        编译(cc1,这里针对c语言,不同的语言由自己的编译器):编译完成“预处理”和“编译”。

        汇编(as):汇编器将汇编语言代码转换成机器(cpu)可以执行的指令。

        链接(ld):链接器将汇编器生成的目标文件和一些标准库(譬如libc)文件组合,形成最终可执行的应用程序。

        gcc涉及的文件类型:

        .c:C源文件

        .cc/.cxx/.cpp:c++源文件

        .i:经过预处理的c源文件

        .s/.S:汇编语言源文件

        .h:头(header)文件

        .o:目标(object)文件

        .a/.so:编译后的静态库(archive)文件和共享库(shared object)文件

        a.out:可执行文件

ELF介绍

        ELF(Executable Format)是一种unix-like系统上的二进制文件格式标准。

        ELF标准中定义的采用ELF格式的文件分为4类:

ELF文件类型说明实例
可重定位文件(relocatable file)内容包含了代码和数据,可以被链接成可执行文件或共享目标文件linux上的.o文件
可执行文件可以直接执行的文件linux上的a.out文件
共享目标文件内容包含了代码和数据,可以作为链接器的输入,在链接阶段和其他的relacatable file或者shared object file一起链接成新的object file;或者在运行阶段,作为动态链接器的输入,和可执行文件结合,作为进程的一部分来运行。

linux上的.so文件

核心转储文件(core dump file)进行意外终止时,系统可以将该进程的部分内容和终止时的其他状态信息保存到该文件中以供调试分析。linux上的core文件

        ELF文件格式:

ELF Header
Program Header Table运行视图
.text程序指令
.init做初始化的一些指令
.data数据:全局变量等
.bss
......

Section Header Table

从链接角度去描述了这个文件的内容

        .text和.init等这些信息放置的时候都会section(节)对齐,但是在运行的时候会合在一起以节省空间,于是有了segment(段)概念,segment的信息存放于program header table中。segment fault就是因为出错的时候在内存中失败。

        ELF文件处理相关工具:

       Binutils官网地址:https://www.gnu.org/software/binutils/

        ar:归档文件,将多个文件打包成一个大文件。

        as:被gcc调用,输入汇编文件,输出目标文件工链接器ld连接。

        ld:gnu链接器,被gcc调用,它把目标文件和各种库文件结合在一起,重定位数据,并链接符号引用。

        objcopy:执行文件格式转换。

        objdump:显示ELF文件的信息。

        readelf:显示更多ELF格式文件的信息(包括DWARF调试信息)

        示例1:

gcc -c hello.c
readelf -h hello.o  // 查看头信息

readelf -S hello.o  // 查看section信息
readelf -SW hello.o

        实例2:

gcc -g -c hello.c
objdump -S hello.o // 显示汇编指令

练习题

        编写程序hello.c

#include <stdio.h>

int main() {
    printf("hello world!\n");
    return 0;
}

        使用 gcc 进行本地编译生成目标文件 hello.o,-m64是 gcc 编译器的一个选项,它指示编译器生成 64 位目标代码。

gcc -c -m64 hello.c

        查看hello.h的头信息        

$ readelf -h hello.o
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:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1060
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14712 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30

        查看hello.o的section header elf

$ readelf -S hello.o
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000318  00000318
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.propert NOTE             0000000000000338  00000338
       0000000000000020  0000000000000000   A       0     0     8
  [ 3] .note.gnu.build-i NOTE             0000000000000358  00000358
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .note.ABI-tag     NOTE             000000000000037c  0000037c
       0000000000000020  0000000000000000   A       0     0     4
  [ 5] .gnu.hash         GNU_HASH         00000000000003a0  000003a0
       0000000000000024  0000000000000000   A       6     0     8
  [ 6] .dynsym           DYNSYM           00000000000003c8  000003c8
       00000000000000a8  0000000000000018   A       7     1     8
  [ 7] .dynstr           STRTAB           0000000000000470  00000470
       0000000000000082  0000000000000000   A       0     0     1
  [ 8] .gnu.version      VERSYM           00000000000004f2  000004f2
       000000000000000e  0000000000000002   A       6     0     2
  [ 9] .gnu.version_r    VERNEED          0000000000000500  00000500
       0000000000000020  0000000000000000   A       7     1     8
  [10] .rela.dyn         RELA             0000000000000520  00000520
       00000000000000c0  0000000000000018   A       6     0     8
  [11] .rela.plt         RELA             00000000000005e0  000005e0
       0000000000000018  0000000000000018  AI       6    24     8
  [12] .init             PROGBITS         0000000000001000  00001000
       000000000000001b  0000000000000000  AX       0     0     4
  [13] .plt              PROGBITS         0000000000001020  00001020
       0000000000000020  0000000000000010  AX       0     0     16
  [14] .plt.got          PROGBITS         0000000000001040  00001040
       0000000000000010  0000000000000010  AX       0     0     16
  [15] .plt.sec          PROGBITS         0000000000001050  00001050
       0000000000000010  0000000000000010  AX       0     0     16
  [16] .text             PROGBITS         0000000000001060  00001060
       0000000000000175  0000000000000000  AX       0     0     16
  [17] .fini             PROGBITS         00000000000011d8  000011d8
       000000000000000d  0000000000000000  AX       0     0     4
  [18] .rodata           PROGBITS         0000000000002000  00002000
       0000000000000011  0000000000000000   A       0     0     4
  [19] .eh_frame_hdr     PROGBITS         0000000000002014  00002014
       0000000000000044  0000000000000000   A       0     0     4
  [20] .eh_frame         PROGBITS         0000000000002058  00002058
       0000000000000108  0000000000000000   A       0     0     8
  [21] .init_array       INIT_ARRAY       0000000000003db8  00002db8
       0000000000000008  0000000000000008  WA       0     0     8
  [22] .fini_array       FINI_ARRAY       0000000000003dc0  00002dc0
       0000000000000008  0000000000000008  WA       0     0     8
  [23] .dynamic          DYNAMIC          0000000000003dc8  00002dc8
       00000000000001f0  0000000000000010  WA       7     0     8
  [24] .got              PROGBITS         0000000000003fb8  00002fb8
       0000000000000048  0000000000000008  WA       0     0     8
  [25] .data             PROGBITS         0000000000004000  00003000
       0000000000000010  0000000000000000  WA       0     0     8
  [26] .bss              NOBITS           0000000000004010  00003010
       0000000000000008  0000000000000000  WA       0     0     1
  [27] .comment          PROGBITS         0000000000000000  00003010
       000000000000002b  0000000000000001  MS       0     0     1
  [28] .symtab           SYMTAB           0000000000000000  00003040
       0000000000000618  0000000000000018          29    46     8
  [29] .strtab           STRTAB           0000000000000000  00003658
       0000000000000203  0000000000000000           0     0     1
  [30] .shstrtab         STRTAB           0000000000000000  0000385b
       000000000000011a  0000000000000000           0     0     1

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

$ objdump -d hello.o
hello:     file format elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:       f3 0f 1e fa             endbr64 
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   callq  *%rax
    1016:       48 83 c4 08             add    $0x8,%rsp
    101a:       c3                      retq   

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:       ff 35 9a 2f 00 00       pushq  0x2f9a(%rip)        # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:       f2 ff 25 9b 2f 00 00    bnd jmpq *0x2f9b(%rip)        # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:       0f 1f 00                nopl   (%rax)
    1030:       f3 0f 1e fa             endbr64 
    1034:       68 00 00 00 00          pushq  $0x0
    1039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt>
    103f:       90                      nop

Disassembly of section .plt.got:

0000000000001040 <__cxa_finalize@plt>:
    1040:       f3 0f 1e fa             endbr64 
    1044:       f2 ff 25 ad 2f 00 00    bnd jmpq *0x2fad(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    104b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001050 <puts@plt>:
    1050:       f3 0f 1e fa             endbr64 
    1054:       f2 ff 25 75 2f 00 00    bnd jmpq *0x2f75(%rip)        # 3fd0 <puts@GLIBC_2.2.5>
    105b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .text:

0000000000001060 <_start>:
    1060:       f3 0f 1e fa             endbr64 
    1064:       31 ed                   xor    %ebp,%ebp
    1066:       49 89 d1                mov    %rdx,%r9
    1069:       5e                      pop    %rsi
    106a:       48 89 e2                mov    %rsp,%rdx
    106d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1071:       50                      push   %rax
    1072:       54                      push   %rsp
    1073:       4c 8d 05 56 01 00 00    lea    0x156(%rip),%r8        # 11d0 <__libc_csu_fini>
    107a:       48 8d 0d df 00 00 00    lea    0xdf(%rip),%rcx        # 1160 <__libc_csu_init>
    1081:       48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 1149 <main>
    1088:       ff 15 52 2f 00 00       callq  *0x2f52(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>
    108e:       f4                      hlt    
    108f:       90                      nop

0000000000001090 <deregister_tm_clones>:
    1090:       48 8d 3d 79 2f 00 00    lea    0x2f79(%rip),%rdi        # 4010 <__TMC_END__>
    1097:       48 8d 05 72 2f 00 00    lea    0x2f72(%rip),%rax        # 4010 <__TMC_END__>
    109e:       48 39 f8                cmp    %rdi,%rax
    10a1:       74 15                   je     10b8 <deregister_tm_clones+0x28>
    10a3:       48 8b 05 2e 2f 00 00    mov    0x2f2e(%rip),%rax        # 3fd8 <_ITM_deregisterTMCloneTable>
    10aa:       48 85 c0                test   %rax,%rax
    10ad:       74 09                   je     10b8 <deregister_tm_clones+0x28>
    10af:       ff e0                   jmpq   *%rax
    10b1:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    10b8:       c3                      retq   
    10b9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

00000000000010c0 <register_tm_clones>:
    10c0:       48 8d 3d 49 2f 00 00    lea    0x2f49(%rip),%rdi        # 4010 <__TMC_END__>
    10c7:       48 8d 35 42 2f 00 00    lea    0x2f42(%rip),%rsi        # 4010 <__TMC_END__>
    10ce:       48 29 fe                sub    %rdi,%rsi
    10d1:       48 89 f0                mov    %rsi,%rax
    10d4:       48 c1 ee 3f             shr    $0x3f,%rsi
    10d8:       48 c1 f8 03             sar    $0x3,%rax
    10dc:       48 01 c6                add    %rax,%rsi
    10df:       48 d1 fe                sar    %rsi
    10e2:       74 14                   je     10f8 <register_tm_clones+0x38>
    10e4:       48 8b 05 05 2f 00 00    mov    0x2f05(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable>
    10eb:       48 85 c0                test   %rax,%rax
    10ee:       74 08                   je     10f8 <register_tm_clones+0x38>
    10f0:       ff e0                   jmpq   *%rax
    10f2:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    10f8:       c3                      retq   
    10f9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001100 <__do_global_dtors_aux>:
    1100:       f3 0f 1e fa             endbr64 
    1104:       80 3d 05 2f 00 00 00    cmpb   $0x0,0x2f05(%rip)        # 4010 <__TMC_END__>
    110b:       75 2b                   jne    1138 <__do_global_dtors_aux+0x38>
    110d:       55                      push   %rbp
    110e:       48 83 3d e2 2e 00 00    cmpq   $0x0,0x2ee2(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    1115:       00 
    1116:       48 89 e5                mov    %rsp,%rbp
    1119:       74 0c                   je     1127 <__do_global_dtors_aux+0x27>
    111b:       48 8b 3d e6 2e 00 00    mov    0x2ee6(%rip),%rdi        # 4008 <__dso_handle>
    1122:       e8 19 ff ff ff          callq  1040 <__cxa_finalize@plt>
    1127:       e8 64 ff ff ff          callq  1090 <deregister_tm_clones>
    112c:       c6 05 dd 2e 00 00 01    movb   $0x1,0x2edd(%rip)        # 4010 <__TMC_END__>
    1133:       5d                      pop    %rbp
    1134:       c3                      retq   
    1135:       0f 1f 00                nopl   (%rax)
    1138:       c3                      retq   
    1139:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001140 <frame_dummy>:
    1140:       f3 0f 1e fa             endbr64 
    1144:       e9 77 ff ff ff          jmpq   10c0 <register_tm_clones>

0000000000001149 <main>:
    1149:       f3 0f 1e fa             endbr64 
    114d:       55                      push   %rbp
    114e:       48 89 e5                mov    %rsp,%rbp
    1151:       48 8d 3d ac 0e 00 00    lea    0xeac(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    1158:       e8 f3 fe ff ff          callq  1050 <puts@plt>
    115d:       90                      nop
    115e:       5d                      pop    %rbp
    115f:       c3                      retq   

0000000000001160 <__libc_csu_init>:
    1160:       f3 0f 1e fa             endbr64 
    1164:       41 57                   push   %r15
    1166:       4c 8d 3d 4b 2c 00 00    lea    0x2c4b(%rip),%r15        # 3db8 <__frame_dummy_init_array_entry>
    116d:       41 56                   push   %r14
    116f:       49 89 d6                mov    %rdx,%r14
    1172:       41 55                   push   %r13
    1174:       49 89 f5                mov    %rsi,%r13
    1177:       41 54                   push   %r12
    1179:       41 89 fc                mov    %edi,%r12d
    117c:       55                      push   %rbp
    117d:       48 8d 2d 3c 2c 00 00    lea    0x2c3c(%rip),%rbp        # 3dc0 <__do_global_dtors_aux_fini_array_entry>
    1184:       53                      push   %rbx
    1185:       4c 29 fd                sub    %r15,%rbp
    1188:       48 83 ec 08             sub    $0x8,%rsp
    118c:       e8 6f fe ff ff          callq  1000 <_init>
    1191:       48 c1 fd 03             sar    $0x3,%rbp
    1195:       74 1f                   je     11b6 <__libc_csu_init+0x56>
    1197:       31 db                   xor    %ebx,%ebx
    1199:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    11a0:       4c 89 f2                mov    %r14,%rdx
    11a3:       4c 89 ee                mov    %r13,%rsi
    11a6:       44 89 e7                mov    %r12d,%edi
    11a9:       41 ff 14 df             callq  *(%r15,%rbx,8)
    11ad:       48 83 c3 01             add    $0x1,%rbx
    11b1:       48 39 dd                cmp    %rbx,%rbp
    11b4:       75 ea                   jne    11a0 <__libc_csu_init+0x40>
    11b6:       48 83 c4 08             add    $0x8,%rsp
    11ba:       5b                      pop    %rbx
    11bb:       5d                      pop    %rbp
    11bc:       41 5c                   pop    %r12
    11be:       41 5d                   pop    %r13
    11c0:       41 5e                   pop    %r14
    11c2:       41 5f                   pop    %r15
    11c4:       c3                      retq   
    11c5:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
    11cc:       00 00 00 00 

00000000000011d0 <__libc_csu_fini>:
    11d0:       f3 0f 1e fa             endbr64 
    11d4:       c3                      retq   

Disassembly of section .fini:

00000000000011d8 <_fini>:
    11d8:       f3 0f 1e fa             endbr64 
    11dc:       48 83 ec 08             sub    $0x8,%rsp
    11e0:       48 83 c4 08             add    $0x8,%rsp
    11e4:       c3                      retq

       

嵌入式开发

        嵌入式开发是一种比较综合性的技术,它不单指纯粹的软件开发技术,也不单是一种硬件配置技术;它是在特定的硬件环境下针对某款硬件进行开发,是一种系统级别的与硬件结合比较紧密的软件开发技术。程序并不是运行在本地,而是运行在特殊的硬件上。

        参与编译和运行的机器根据其角色可以分成以下三类:

        -build系统:生成编译器可执行程序的计算机。编译器在build系统上编译出来的。 

        -host系统:运行编译器可执行程序,编译链接应用程序的计算机系统。

        -target系统:运行应用程序的计算机系统。

        根据build/host/target的不同组合我们可以得到如下的编译方式分类:

        -本地(native)编译:build==host==target

        -交叉(cross)编译:build==host!=target

whereis gcc
ls -l /usr/bin/gcc
ls -l /usr/bin/gcc-9 

QEMU

        QEMU是一套由(Fabrice Bellard)编写的以GPL许可证分发源码的计算机系统模拟软件,在GNU/Linux平台上使用广泛。 

        QEMU,支持多种体系架构。譬如:IA-32(x86),AMD 64, MIPS 32/64,RISC-V 32/64等等。

        QEMU有两种主要运作模式:

        -user mode: 直接运行应用程序 (比如说hello.o运行直接输出“hello”)

        -system mode:模拟整个计算机系统,包括中央处理器及其他周边设备。     

MAKE

        make是一种自动化工程管理工具。

       makefile由一条或者多条规则组成。

        每条规则由三要素构成:

        -target:目标,可以是obj文件也可以是可歘看文件。

        -prerequisites:生成target所需要的依赖。

        -command:为了生成target需要执行的命令,可以有多条。

       模板:

target...:prerequisites...
    command...
    ...

        例子:

hello: hello.c
    gcc hello.c -o hello

练习题

        用riscv编译器编译hello.c,查看头信息、section信息和进行反汇编并查看c程序源码和机器指令的对应关系

$ riscv64-unknown-elf-gcc -o hello hello.c
$ readelf -h hello
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:                              EXEC (Executable file)
  Machine:                           RISC-V
  Version:                           0x1
  Entry point address:               0x10116
  Start of program headers:          64 (bytes into file)
  Start of section headers:          22472 (bytes into file)
  Flags:                             0x5, RVC, double-float ABI
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         3
  Size of section headers:           64 (bytes)
  Number of section headers:         15
  Section header string table index: 14

$ readelf -S hello
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         00000000000100e8  000000e8
       00000000000024ee  0000000000000000  AX       0     0     2
  [ 2] .rodata           PROGBITS         00000000000125d8  000025d8
       0000000000000012  0000000000000000   A       0     0     8
  [ 3] .eh_frame         PROGBITS         0000000000013000  00003000
       0000000000000004  0000000000000000  WA       0     0     8
  [ 4] .init_array       INIT_ARRAY       0000000000013008  00003008
       0000000000000010  0000000000000008  WA       0     0     8
  [ 5] .fini_array       FINI_ARRAY       0000000000013018  00003018
       0000000000000008  0000000000000008  WA       0     0     8
  [ 6] .data             PROGBITS         0000000000013020  00003020
       00000000000009a0  0000000000000000  WA       0     0     8
  [ 7] .sdata            PROGBITS         00000000000139c0  000039c0
       0000000000000020  0000000000000000  WA       0     0     8
  [ 8] .sbss             NOBITS           00000000000139e0  000039e0
       0000000000000038  0000000000000000  WA       0     0     8
  [ 9] .bss              NOBITS           0000000000013a18  000039e0
       0000000000000588  0000000000000000  WA       0     0     8
  [10] .comment          PROGBITS         0000000000000000  000039e0
       0000000000000034  0000000000000001  MS       0     0     1
  [11] .riscv.attributes RISCV_ATTRIBUTE  0000000000000000  00003a14
       000000000000004b  0000000000000000           0     0     1
  [12] .symtab           SYMTAB           0000000000000000  00003a60
       00000000000015d8  0000000000000018          13   150     8
  [13] .strtab           STRTAB           0000000000000000  00005038
       000000000000070c  0000000000000000           0     0     1
  [14] .shstrtab         STRTAB           0000000000000000  00005744
       000000000000007e  0000000000000000           0     0     1

$ objdump -d hello
hello:     file format elf64-little

objdump: can't disassemble for architecture UNKNOWN!

          

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闻林禹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值