LA32R汇编编程简介
LA32R汇编编程学习环境介绍
交叉工具链
在进行基于LA32R的应用程序或操作系统开发时,由于我们手边缺少真实的以LA32R为架构的CPU,我们需要借助交叉工具链进行代码的编译与程序的模拟运行。
在交叉开发的过程中,应区分宿主机和目标机。目标机的指令集架构是期望运行的架构,也就是本手册的LA32R架构;宿主机是执行编译、提供模拟运行环境的机器,如我们常用的x86架构机器。交叉编译要实现的目标是在宿主机上生成目标机架构的代码,模拟运行实现的目标是在宿主机上运行目标机架构的程序。
下表中的工具为LA32R汇编编程环境所需的工具与软件环境,请选择对应版本下载好,下一小节将介绍它们的使用方法。
| 工具 | 用途 | 下载地址 |
|---|---|---|
| loongarch32r-linux-gnusf-{gcc/objdump/gdb/...} | 交叉编译器、反汇编器、调试器…… | 工具发行版地址 |
| la32r-QEMU | LA32R模拟器 | qemu发行版地址 |
简单的LA32R汇编编程学习环境
这里为初学者提供一个简易的LA32R汇编编程学习环境,无需同学们自己搭建环境,可以快速上手。
克隆LA32R指令集学习指导手册仓库,进入try-example目录:
参照该目录下的README.md,按照步骤生成已包含交叉工具链和qemu的docker容器环境,即可进行初步尝试,在docker内运行该目录下提供的汇编源代码样例。汇编源代码样例为汇编编程示例一节中给出的三个例子。
自行搭建环境与工具使用方法介绍
如果同学们想要尝试自己搭建工具链环境,可以参考以下内容,搭建过程也并不困难。以下内容也包含工具的使用方法。
loongarch32r-linux-gnusf-*
交叉工具链发行版支持的宿主机架构包括x86_64、aarch64和LA64架构。下载后可以通过
$ echo 'export PATH=<your loongarch32r gnu toolchain path>/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc
将其添加至环境变量中并使其生效。可以在命令行中输入loong后按<TAB>键查看是否能够自动联想出loongarch32r-linux-gnusf-,来检查路径配置是否正确。
工具的使用方法与不带交叉前缀的使用方法一致。最常使用的两个工具为gcc和objdump。前者用于编译.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_64和aarch64两种架构的qemu,使用这两种PC架构的同学无需编译qemu,可以直接下载解压运行,跳过此步。需要自己编译qemu源码的同学可以阅读这部分内容。
因为提供了qemu源码,我们可以在各自宿主机上进行编译运行。编译qemu前请阅读仓库的wiki,安装好编译时的依赖。注意编译的qemu是qemu-loongarch32(linux-user)。生成的qemu位于<your qemu src path>/build/qemu-loongarch32。可以编写如下脚本进行编译:
| build.sh | |
|---|---|
qemu运行
类似地,我们可以编写运行脚本user_run.sh。
其中参数-L用于提供交叉运行所需的正确的头文件和库文件,该路径位于下载的交叉工具链sysroot目录下,替换为自己的路径即可。
sysroot路径
对于x86_64和LA64而言,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 |
|---|---|
|
|
|
|
|
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->chard->decimalo->octalx->hex |
x /<format> <symbol> |
x /10x 0x10580x /20i 0x10580x /20i $pc |
以某种格式打印内存地址的值<format> = <num><basic_format><basic_format>:c->chard->decimalo->octalx->hexi->instruction |
disassemble |
- | 查看当前PC所在地址的一段汇编指令 |
layout asm |
- | 以可视化的方式查看指令的执行,使用Ctrl x + a退出该模式 |