没有关于 ARM V7 内联汇编的问题可以回答我的问题,所以我发了一篇帖子。我想将 C 变量的值移动到 r0-r2 中,反之亦然 - 从寄存器移动到 C 变量中。但是,我的代码总是将相同的值 - 12 - 加载到寄存器中。有人能告诉我如何实现我的目标吗?
// syscalls.h
#ifndef SYSCALL_H
#define SYSCALL_H
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define SYSCALL_ID_EXIT 1
#define SYSCALL_ID_CREATE_THREAD 2
#define SYSCALL_ID_GETC 3
#define SYSCALL_ID_PUTC 4
#define SYSCALL_ID_SLEEP 5
#define SYSCALL_ID_UNDEFINED 6
#ifndef __ASSEMBLER__
//...
// syscalls.c
// ...
void syscall_create_thread(void (*f) (void *), void * args, unsigned int arg_size){
unsigned int func = (unsigned int) f;
unsigned int arguments = (unsigned int) args;
unsigned int argument_size = (unsigned int) arg_size;
asm("mov r0, %0" : "=r"(func)::"r0");
asm("mov r1, %0" : "=r"(arguments)::"r1");
asm("mov r2, %0" : "=r"(argument_size)::"r2");
asm("mov r7, #" TOSTRING(SYSCALL_ID_CREATE_THREAD));
asm("SVC #0");
}
您的具体用例可以像下面这样简单完成:
这依赖于这样一个事实:您的体系结构的调用约定定义了传递给函数的参数
r0, r1...
由调用者放置在寄存器中。当您创建函数时,naked
您告诉编译器不要为该函数生成任何序言/结尾,也就是说不要创建堆栈框架、保存被调用者保存的寄存器,甚至不要添加ret
指令。但这意味着您也需要格外小心,并自己添加缺失的部分。以下是最终的示例代码和生成的程序集,以证明它可以工作:
以及生成的程序集(由我注释):
在Godbolt上查看
编辑:显然,当函数为“裸函数”时,标记为破坏没有任何效果
r7
,因此它不会像应该的那样被“保存为被调用方”,因此需要对上面的代码进行一些修改,以确保r7
值在函数内被保存和恢复syscall_create_thread()
。最简单的方法是在非被调用方保存的寄存器之一中执行此操作,例如r3
或r4
。或者可以在堆栈上完成。