命令行的艺术

linux的命令行是非常强大的工具。本篇旨在将学习中遇到的美丽的命令行分享出来。

文本处理

eg1

需求:输入文件inst.S,输出文件inst。
为了测试CPU的执行,我必须先得到一个二进制串,手写二进制是不显示的,因此我需要将riscv汇编指令映射为二进制串的过程。(应该没有人会手写二进制)。

1
2
3
4
add x1, x2, x3
add x2, x2, x3
add x3, x2, x3
add x4, x2, x3
1
003100b3
1
riscv64-linux-gnu-as -o inst.o inst.S && riscv64-linux-gnu-objdump -d inst.o | grep -E "[0-9|a-f]+:" | cut -c7-14 > inst && paste inst inst.S
  1. 将汇编编译为elf可执行文件。riscv64-linux-gnu-toolchain中的工具可以进行riscv指令集的交叉编译。因此要将riscv的汇编汇编为可执行文件,可以使用riscv64-linux-gnu-as汇编器。结果生成一个inst.o文件。

    1
    riscv64-linux-gnu-as -o inst.o inst.S
  2. 将elf可执行文件反汇编为适合人类阅读的形式。使用riscv64-linux-gnu-objdump工具。

    1
    riscv64-linux-gnu-objdump -d inst.o

    结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    inst.o: file format elf64-littleriscv


    Disassembly of section .text:

    0000000000000000 <.text>:
    0: 003100b3 add ra,sp,gp
    4: 00310133 add sp,sp,gp
    8: 003101b3 add gp,sp,gp
    c: 00310233 add tp,sp,gp

    我们只要<.text>后的内容

  3. 使用grep -E,以正则表达式的方式将后四行提炼出来,因为这四行都以数字0-9或a-f开头(16进制)(但是实际上只会以048cf开头,因为指令每次+4字节)。

    1
    riscv64-linux-gnu-objdump -d inst.o | grep -E "[0-9|a-f]+:"

    结果:

    1
    2
    3
    4
    0:   003100b3                add     ra,sp,gp
    4: 00310133 add sp,sp,gp
    8: 003101b3 add gp,sp,gp
    c: 00310233 add tp,sp,gp
  4. 使用cut工具截取其中的字符

    1
    riscv64-linux-gnu-objdump -d inst.o | grep -E "[0-9|a-f]+:" | cut -c7-14

    结果:

    1
    2
    3
    4
    003100b3
    00310133
    003101b3
    00310233
  5. 输出到文件inst

    1
    riscv64-linux-gnu-objdump -d inst.o | grep -E "[0-9|a-f]+:" | cut -c7-14 > inst

    如果既想在屏幕中打印,又想输出到文件中,可以使用tee命令:

    1
    riscv64-linux-gnu-objdump -d inst.o | grep -E "[0-9|a-f]+:" | cut -c7-14 | tee -a inst
  6. 同时在屏幕中输出指令和注释信息

    1
    paste inst inst.S

    结果:

    1
    2
    3
    4
    003100b3        add x1, x2, x3
    00310133 add x2, x2, x3
    003101b3 add x3, x2, x3
    00310233 add x4, x2, x3