【问题标题】:Mix Assembly and C function in linux kernel - x64 mode在 Linux 内核中混合汇编和 C 函数 - x64 模式
【发布时间】:2018-07-15 23:34:20
【问题描述】:

我正在学习汇编语言,我创建了一个简单的 linux 内核模块来尝试如何从模块调用汇编函数,而后者又调用 C 函数。代码编译得很好。但是,当我尝试插入模块时,会导致内核崩溃。我从这篇文章中得到了这个想法:Calling C functions from x86 assembly language。我想知道是否有人可以帮助我理解为什么它不起作用。

首先是汇编代码:

#include <linux/linkage.h>
ENTRY(sample_assembly_function)
pushq $10
call printMessage
add $0x4, %rsp
END(sample_assembly_function)

第二个文件是示例模块文件:

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Proprietary");

void sample_assembly_function(void);

void printMessage(int num)
{
 printk(KERN_ERR "MixAssemblyAndC: PrintMessage=%d.\n", num);
}

static int __init AModule_init(void)
{
sample_assembly_function();
return 0;
}

static void __exit AModule_exit(void)
{
printk("MixAssemblyAndC: Goodbye, world!\n");
}

module_init(AModule_init);
module_exit(AModule_exit);

最后这是 Makefile:

KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD=$(shell pwd)
obj-m += test.o
test-y := AModule.o ASample.o

all:
    $(MAKE) -C $(KERNELDIR) M=$(PWD)

clean:
     $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

install:
     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

【问题讨论】:

标签: c assembly linux-kernel x86-64 calling-convention


【解决方案1】:

使用Linux 64-bit System V ABI 调用约定时,您在寄存器RDI、RSI、RDX、RCX、R8R9 中传递前6 个整数类或指针参数.任何剩余的参数都被压入堆栈。您在问题中链接到的代码是 32 位代码,并且使用 Linux i386 System V ABI 作为调用约定。这与 64 位代码不兼容。

只需执行mov $10, %rdi 即可加载第一个参数。最好你可以做mov $10, %edi。后者将值 10 移动到 EDI,但由于目标是 32 位寄存器,处理器会自动将值零扩展到 64 位寄存器,因此将 10 移动到 RDI。后者是一种较短的编码。

您需要一个ret 指令来结束您的汇编语言例程。生成的代码应如下所示:

#include <linux/linkage.h>

ENTRY(sample_assembly_function)
mov $10, %edi
call printMessage
ret
END(sample_assembly_function)

由于callret 之前的最后一件事,您也可以只使用jmp printMessage (Tail Call)。当到达printMessage 中的ret 时,控制将返回到调用sample_assembly_function 的函数。这段代码应该可以工作:

ENTRY(sample_assembly_function)
mov $10, %edi
jmp printMessage
END(sample_assembly_function)

【讨论】:

  • 感谢您的建议。它确实帮助我解决了问题。谢谢。我还有另一个问题:我添加了一个新函数,它只是尝试添加 2 个数字(将 2 个整数作为参数传递)然后 printk 结果。与我原来的问题完全相同的情况。 Add2Numbers 函数在同一个 C 文件中定义,然后我尝试从同一个程序集文件中调用它(而不是调用 PrintMessage)。但是,我收到此编译警告:警告:“Add2Numbers”[/home/bob/MixAssemblyAndC/test.ko] 未定义!有什么建议吗?
  • @iceheart 您可以针对因该错误而失败的代码提出一个新问题
  • 对不起。这是我的错。我会更加努力地跟进我自己的问题。感谢您的回答。我可以接受它作为我问题的答案。
  • 我猜你是对的,我可能有错字。它现在正在工作。
猜你喜欢
  • 2013-01-29
  • 1970-01-01
  • 2016-01-22
  • 2020-05-09
  • 1970-01-01
  • 2012-11-20
  • 2017-05-03
  • 1970-01-01
相关资源
最近更新 更多