ARM 内联 asm:退出系统调用并从内存中读取值
- 2024-10-31 08:38:00
- admin 原创
- 40
问题描述:
问题
我想在 Linux Android 设备上使用内联汇编执行 ARM 中的退出系统调用,并且我希望从内存中的某个位置读取退出值。
例子
如果不提供这个额外的参数,调用的宏如下所示:
#define ASM_EXIT() __asm__("mov %r0, #1
" \n "mov %r7, #1
" \n "swi #0")
这很有效。为了接受一个论点,我将其调整为:
#define ASM_EXIT(var) __asm__("mov %r0, %0
" \n "mov %r7, #1
" \n "swi #0" \n : \n : "r"(var))
我这样称呼它:
#define GET_STATUS() (*(int*)(some_address)) //gets an integer from an address
ASM_EXIT(GET_STATUS());
错误
无效的‘asm’:操作数超出范围
我无法解释为什么会出现此错误,因为我在上面的代码片段中使用了一个输入变量 (%0/var)。此外,我尝试使用常规变量,但仍然出现相同的错误。
解决方案 1:
扩展 asm 语法需要写入才能在 asm 输出中%%
获取单个。例如对于 x86:%
asm("inc %eax") // bad: undeclared clobber
asm("inc %%eax" ::: "eax"); // safe but still useless :P
%r7
被视为r7
操作数。正如评论者指出的那样,只需省略%
s,因为对于 ARM 来说,您不需要它们,即使使用 GNU 也是如此as
。
ARM没有像 x86 那样对特定寄存器中的操作数进行请求的特定寄存器约束。(例如,x86 的"a"
约束只允许编译器选择(的底部)rax
)。
您可以使用register int var asm ("r7")
强制 var 使用特定寄存器,然后使用约束"r"
并假定它将位于该寄存器中。(事实上,这是唯一支持的用法register ... asm("regname")
: https: //gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html)
这生成了高效的代码,避免了在 reg-reg 移动上浪费指令。
在 Godbolt Compiler Explorer 上查看:
__attribute__((noreturn)) static inline void ASM_EXIT(int status)
{
register int status_r0 asm ("r0") = status;
register int callno_r7 asm ("r7") = 1;
asm volatile("swi #0
"
:
: "r" (status_r0), "r" (callno_r7)
: "memory" // any side-effects on shared memory need to be done before this, not delayed until after
);
// __builtin_unreachable(); // optionally let GCC know the inline asm doesn't "return"
}
#define GET_STATUS() (*(int*)(some_address)) //gets an integer from an address
void foo(void) { ASM_EXIT(12); }
push {r7} @ # gcc is still saving r7 before use, even though it sees the "noreturn" and doesn't generate a return
movs r0, #12 @ stat_r0,
movs r7, #1 @ callno,
swi #0
# yes, it literally ends here, after the inlined noreturn
void bar(int status) { ASM_EXIT(status); }
push {r7} @
movs r7, #1 @ callno,
swi #0 # doesn't touch r0: already there as bar()'s first arg.
由于您始终希望从内存中读取值,因此可以使用"m"
约束并在内联汇编中包含ldr
。这样,您就不需要使用register int var asm("r0")
技巧来避免浪费mov
该操作数。
也可能mov r7, #1
并不总是需要,这register asm()
也是我使用语法的原因。如果 gcc 想要1
函数中某个寄存器中的常量,它可以这样做,r7
因此它已经存在于 ASM_EXIT 中。
任何时候,只要 GNU C 内联 asm 语句的第一个或最后一个指令是mov
指令,就可能有办法通过更好的约束将其删除。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件