Skip to content

LA32R汇编编程简介

LA32R汇编编程学习环境介绍

交叉工具链

在进行基于LA32R的应用程序或操作系统开发时,由于我们手边缺少真实的以LA32R为架构的CPU,我们需要借助交叉工具链进行代码的编译与程序的模拟运行。

在交叉开发的过程中,应区分宿主机和目标机。目标机的指令集架构是期望运行的架构,也就是本手册的LA32R架构;宿主机是执行编译、提供模拟运行环境的机器,如我们常用的x86架构机器。交叉编译要实现的目标是在宿主机上生成目标机架构的代码,模拟运行实现的目标是在宿主机上运行目标机架构的程序。

下表中的工具为LA32R汇编编程环境所需的工具与软件环境,请选择对应版本下载好,下一小节将介绍它们的使用方法。

工具 用途 下载地址
loongarch32r-linux-gnusf-{gcc/objdump/gdb/...} 交叉编译器、反汇编器、调试器…… 工具发行版地址
la32r-QEMU LA32R模拟器 qemu发行版地址

简单的LA32R汇编编程学习环境

这里为初学者提供一个简易的LA32R汇编编程学习环境,无需同学们自己搭建环境,可以快速上手。

克隆LA32R指令集学习指导手册仓库,进入try-example目录:

$ git clone https://gitee.com/shepherdwang/la32r_study_note.git
$ cd la32r_study_note/try-example

参照该目录下的README.md,按照步骤生成已包含交叉工具链和qemu的docker容器环境,即可进行初步尝试,在docker内运行该目录下提供的汇编源代码样例。汇编源代码样例为汇编编程示例一节中给出的三个例子。

自行搭建环境与工具使用方法介绍

如果同学们想要尝试自己搭建工具链环境,可以参考以下内容,搭建过程也并不困难。以下内容也包含工具的使用方法。

loongarch32r-linux-gnusf-*

交叉工具链发行版支持的宿主机架构包括x86_64aarch64LA64架构。下载后可以通过

$ echo 'export PATH=<your loongarch32r gnu toolchain path>/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc

将其添加至环境变量中并使其生效。可以在命令行中输入loong后按<TAB>键查看是否能够自动联想出loongarch32r-linux-gnusf-,来检查路径配置是否正确。

工具的使用方法与不带交叉前缀的使用方法一致。最常使用的两个工具为gccobjdump。前者用于编译.c.S源文件生成目标机可执行程序;后者用于生成反汇编文件,常用于debug,查看指令地址PC和指令inst的关系,查看变量的内存地址等等,它的不同参数会输出不同的内容,可以查阅GNU工具手册objdump部分了解更多。

# compile source
$ loongarch32r-linux-gnusf-gcc <file_name>.S -o <file_name>

# dump disassembly file
$ loongarch32r-linux-gnusf-objdump -D <file_name> > <file_name>.s

la32r-QEMU

通过qemu(Quick Emulator),我们可以在宿主机上模拟运行我们编写的LA32R汇编程序。目前LA32R的qemu对下述两种运行模式均得到了支持。因为本手册是用于LA32R汇编程序的学习,我们编写的汇编程序在User Mode的qemu上运行即可。

QEMU的两种运行模式:

User Mode(用户模式):用户只需要将目标架构程序放在QEMU中运行即可,其他的事情全部由QEMU虚拟机来完成,不需要用户自定义内核和虚拟磁盘等文件。

System Mode(系统模式):用户需要为QEMU指定运行的内核或者虚拟硬盘等文件。

qemu编译

la32r-QEMU仓库发行版中已经为大家提供了x86_64aarch64两种架构的qemu,使用这两种PC架构的同学无需编译qemu,可以直接下载解压运行,跳过此步。需要自己编译qemu源码的同学可以阅读这部分内容。

因为提供了qemu源码,我们可以在各自宿主机上进行编译运行。编译qemu前请阅读仓库的wiki,安装好编译时的依赖。注意编译的qemu是qemu-loongarch32(linux-user)。生成的qemu位于<your qemu src path>/build/qemu-loongarch32。可以编写如下脚本进行编译:

build.sh
1
2
3
4
5
6
7
8
9
#!/bin/bash
if [ ! -d "build" ]; then
    mkdir build
fi
cd build
../configure \
    --target-list=loongarch32-linux-user \
    --disable-werror --enable-debug
make -j`nproc`
qemu运行

类似地,我们可以编写运行脚本user_run.sh

1
2
3
4
#!/bin/bash
/path/to/your/qemu-loongarch32 \
    -L /path/to/sysroot \
    /path/to/loongarch32r-executable
1
2
3
4
5
#!/bin/bash
/path/to/your/qemu-loongarch32 \
    -g 1234 \
    -L /path/to/sysroot \
    /path/to/loongarch32r-executable

其中参数-L用于提供交叉运行所需的正确的头文件和库文件,该路径位于下载的交叉工具链sysroot目录下,替换为自己的路径即可。

sysroot路径

对于x86_64LA64而言,sysroot路径为<your loongarch32r gnu toolchain path>/loongarch32r-linux-gnusf/sysroot

对于aarch64而言,sysroot路径为<your loongarch32r gnu toolchain path>/sysroot

如果在qemu上运行出错,需要用gdb来debug,可以利用loongarch32r-linux-gnusf-gdb通过端口连接后进行交叉调试。此时需要添加-g 1234配置供gdb连接的端口号,让qemu不自动运行,与gdb连接后再运行。请注意,该参数需要放在可执行文件路径前面。

qemu与gdb的连接过程

如果在qemu上程序运行出错,此时我们可以利用gdb进行debug。前面提到,可以在qemu运行时添加-g 1234参数,等待gdb通过端口1234来连接。连接后,像调试普通宿主机程序一样调试即可。

宿主机 terminal 1: qemu宿主机 terminal 2: gdb
# start qemu
$ cd <your qemu path>
$ ./user_run_gdb.sh
# qemu wait for connection
$ cd <your executable path>
# load file's symbol table
$ loongarch32r-linux-gnusf-gdb <file_name>

# connected to gdb
# at gdb terminal
(gdb) target remote :1234
(gdb) b *main
(gdb) b <somewhere_you_want>
(gdb) c
# qemu start to run


# … reach breakpoints
# trail for bugs
(gdb) <command>

gdb常用命令

命令 例子 用法
c - 继续执行,直到遇到断点
si - 执行下一条指令,如果有函数调用,则进入函数内部
ni - 执行下一条指令,即使有函数调用,也不会进入函数内部
i r
(info registers)
- 查看全部通用寄存器值
b *<symbol> b *main 在标号处设断点
b *<addr> b *0x10518 在某地址处设断点
p /<basic_format> <symbol> p /x $sp 以某种格式打印某个标号(寄存器或变量)的值
<basic_format>:
c->char
d->decimal
o->octal
x->hex
x /<format> <symbol> x /10x 0x10580

x /20i 0x10580

x /20i $pc
以某种格式打印内存地址的值
<format> = <num><basic_format>
<basic_format>:
c->char
d->decimal
o->octal
x->hex
i->instruction
disassemble - 查看当前PC所在地址的一段汇编指令
layout asm - 以可视化的方式查看指令的执行,使用Ctrl x + a退出该模式