Пример, приведенный ниже, должен работать в системе aarch64-linux-gnu - он работает с использованием qemu-aarch64 3.0 в моей системе x86_64 linux.
Самый краткий / слабосвязанный источник информации для целей обучения будет musl-libc Исходный код, по моему скромному мнению:
- syscall_arch.h содержит функции _syscall, которые будут использоваться в зависимости от количества аргументов, требуемых данным syscall,
- syscall.h .in содержит определения для всех системных вызовов.
Затем мы должны использовать:
static inline long __syscall1(long n, long a)
{
register long x8 __asm__("x8") = n;
register long x0 __asm__("x0") = a;
__asm_syscall("r"(x8), "0"(x0));
}
и __NR_exit:
#define __NR_exit 93
#define __NR_exit_group 94
Базовым примером в C будет syscall-exit.c:
#include "syscall_arch.h"
#include "syscall.h.in"
int main(void)
{
// exiting with return code 1.
__syscall1(__NR_exit, 1);
// we should have exited.
for (;;);
}
Компиляция / выполнение / проверка кода возврата:
/opt/linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -static -O0 -o exit-syscall exit-syscall.c
qemu-aarch64 exit-syscall
echo $?
1
Внимательно рассмотрим сгенерированный код для main () и __syscall1 (), используя:
/opt/linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objdump -D exit-syscall > exit-syscall.lst
будет выглядеть так:
0000000000400554 <main>:
400554: a9bf7bfd stp x29, x30, [sp, #-16]!
400558: 910003fd mov x29, sp
40055c: d2800021 mov x1, #0x1 // #1
400560: d2800ba0 mov x0, #0x5d // #93
400564: 97fffff4 bl 400534 <__syscall1>
0000000000400534 <__syscall1>:
400534: d10043ff sub sp, sp, #0x10
400538: f90007e0 str x0, [sp, #8]
40053c: f90003e1 str x1, [sp]
400540: f94007e8 ldr x8, [sp, #8]
400544: f94003e0 ldr x0, [sp]
400548: d4000001 svc #0x0
40054c: 910043ff add sp, sp, #0x10
400550: d65f03c0 ret
См. Документ " Стандарт вызова процедур для 64-битной архитектуры ARM (AArch64) " для получения дополнительной информации.
Следовательно, Aarch64-эквивалент вашего кода x86_64 будет выглядеть как exit-asm.c:
void main(void) {
/* exit system call - calling NR_exit with 1 as the return code*/
asm("mov x0, #1;"
"mov x8, #93;"
"svc #0x0;"
);
for (;;);
}
/opt/linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -static -o example example.c
qemu-aarch64 example
echo $?
1
Обратите внимание, что реализация exit () в glibc вызывает __NR_exit_group перед вызовом __NR_exit.