ARM V7内联汇编:C变量与寄存器值互传问题求助
ARMv7内联汇编实现C变量与r0-r2的双向传递问题解决
你的核心问题是内联汇编的操作数方向搞反,且拆分的独立asm块被编译器优化/重排,导致寄存器加载了意外值(比如固定12)。以下是具体分析和修复方案:
问题根源
- 操作数方向错误:你写的
asm("mov r0, %0" : "=r"(func))是把r0的值写入func变量(输出约束),但你实际需要的是把func的值加载到r0(输入约束),完全搞反了数据流向。 - 独立asm块的顺序风险:多个单独的
asm语句没有约束执行顺序,编译器可能会调整指令位置,甚至优化掉看似无用的mov指令,导致寄存器被其他代码覆盖出现固定值。 - 缺少volatile和破坏寄存器声明:未加
volatile可能让编译器优化掉汇编块,未声明被修改的寄存器(如r7)会导致编译器错误地复用这些寄存器。
修复方案(双向传递:变量→寄存器→变量)
如果需要实现C变量值传入寄存器,同时系统调用后寄存器值写回C变量,可以将所有汇编指令放到一个asm volatile块中,正确指定输入输出约束:
#include "syscalls.h" void syscall_create_thread(void (*f) (void *), void * args, unsigned int arg_size, unsigned int *thread_id) { unsigned int func = (unsigned int)f; unsigned int arguments = (unsigned int)args; unsigned int arg_size_copy = arg_size; asm volatile ( "mov r7, #" TOSTRING(SYSCALL_ID_CREATE_THREAD) "\n\t" "svc #0" // 输出约束:SVC执行后,将r0/r1/r2的值写回对应变量 : "=r"(func), "=r"(arguments), "=r"(arg_size_copy) // 输入约束:将变量值加载到r0/r1/r2(%0对应r0,%1对应r1,%2对应r2) : "0"(func), "1"(arguments), "2"(arg_size_copy) // 破坏寄存器列表:告诉编译器这些寄存器的值会被修改 : "r7", "memory" ); // 示例:将r0返回的线程ID输出 if (thread_id != NULL) { *thread_id = func; } }
简化方案(单向传递:变量→寄存器)
如果只需要把C变量的值加载到r0-r2,不需要写回,可以直接指定寄存器输入约束,代码更简洁:
#include "syscalls.h" void syscall_create_thread(void (*f) (void *), void * args, unsigned int arg_size) { asm volatile ( "mov r7, #" TOSTRING(SYSCALL_ID_CREATE_THREAD) "\n\t" "svc #0" : // 无输出约束 // 直接指定将变量值放入r0/r1/r2 : "r0"((unsigned int)f), "r1"((unsigned int)args), "r2"(arg_size) : "r7", "memory" ); }
关键说明
asm volatile:强制编译器不优化、不重排该汇编块,保证指令按顺序执行。- 输入输出约束:
"=r"(var)表示将寄存器值写入var(输出);"0"(var)表示使用和第0个输出约束相同的寄存器,将var的值加载到该寄存器(输入)。 - 破坏列表:
"r7"声明r7被修改,"memory"告诉编译器系统调用可能修改内存,避免编译器缓存变量到寄存器。
内容的提问来源于stack exchange,提问作者user28496108
相关产品推荐
相关产品推荐

