准备
硬件需求:一台可执行ARM 汇编的算力设备,可以是Raspberry Pi, 也可以是其他云端的虚拟机,也可以利用QEMU去仿真。
资料
查阅ARM架构的各种syscall信息
https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md
Documentation – Arm Developerhttps://developer.arm.com/documentation/ddi0406/latest/
基础知识
寄存器
r0 -- r6: general purpose register
r7: the special purpose register stores the actual system call code/number
sp: stack pointer, next available position on the stack
关键词
.global meakes the "_start" label visible outside the program for the linker
The "_start" label names a certain location in memory
.global _start
section holds the instruction of the program.
.section .text
mov 可以把一个immediate number传入寄存器, 使用0x作为前缀,可以让系统知道这是hex 数字,否则为decimal。另外,数字前面需要加上 #
swi 是一个syscall,称为Software Interrupt.参考 Documentation – Arm Developer
.start
mov r0,#0x42
mov r7, #1
swi 0
代码完整部分
.global _start
.section .text
_start:
mov r0,#42
mov r7,#1
swi 0
Assembly stage
编译后生成hello.o文件,该文件包含机器码,但是需要解决unresolved symbols
as hello.s -o hello.o
LInking stage
基于 .o文件生成二进制文件,对于.o中需要的库和符号进行寻找。
基于.o文件生成可执行文件,对应的报错是,有两个_start,这是因为
default C runtime (CRT) 也包含 _start
符号 在 crt1.o中。
对应的解决方案是避免在编译时引入std库,如下图所示,我们可以正常进行编译。
查看文件信息
如果打开文件,可以看到最开始的就是ELF三个字母。
在执行完文件后,我们可以看到,系统的exit code发生了变化。
$? Expands to the exit status of the most recently executed foreground pipeline.
参考链接: