我有这段代码
int64_t ret;
char *fmt = "\n\n\n%s\n\n\n";
char *s;
s = kmalloc(13, GFP_KERNEL);
memcpy(s, "Hello world!\0", 13);
__asm__ __volatile__ (
"movq %2, %%rdi;"
"movq %1, %%rsi;"
"movq $2, %%rax;"
"call printk;"
"movq %%rax, %0;"
: "=r" (ret)
: "r" (s), "r" (fmt)
:
);
__asm__ __volatile__ (
"movq %0, %%rdi;"
"movq $1, %%rax;"
"call kfree;"
:
: "r" (s)
:
);
return ret;
在kfree
来电时崩溃。它一定是傻事,但我不知道它是什么。有什么问题?
编辑:“崩溃”==内核模块触发Oops。
编辑:如果我使用m
代替r
,似乎工作得很好。但为什么呢?
答案 0 :(得分:3)
您应该查看生成的汇编代码(使用-S
的{{1}}选项)以确切了解正在发生的事情。
我猜测问题是你没有为gcc
块指定正确的clobbers。请记住,某些寄存器可以被被调用的函数自由使用。编译器不处理内联asm块的内容,因此它不知道里面有printk
。它期望未指定为输出或clobber的寄存器将从asm块中保持不变。因此,我假设编译器将变量call
缓存到s
或您使用printk
,rax
和rdi
所销毁的寄存器中也不要告诉编译器。请注意,存在特定的寄存器约束,因此您可以使用它们而不是在汇编中移动参数。
另请注意rsi
(实际上rax
)仅用于varargs和stdargs函数,即使这样,它也只包含通过sse vector(al
)传递的参数数量寄存器,而不是总数。有关更多信息,请参阅x86-64 ABI文档。
最后,如果你真的想编写asm代码,你应该考虑编写独立的asm模块而不是C语言。你可以省去一些头痛。有关示例,请参阅this question。