[英]Mix Assembly and C function in linux kernel - x64 mode
我正在學習匯編語言,我創建了一個簡單的 linux 內核模塊來嘗試如何從模塊調用匯編函數,然后調用 C 函數。 代碼編譯得很好。 但是,當我嘗試插入模塊時,它會導致內核崩潰。 我從這篇文章中得到了想法: 從 x86 匯編語言調用 C 函數。 我想知道是否有人可以幫助我理解為什么它不起作用。
首先是匯編代碼:
#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
使用Linux 64 位 System V ABI調用約定時,您在寄存器RDI、RSI、RDX、RCX、R8和R9 中傳遞前 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)
由於call
是ret
之前的最后一件事,因此您也可以只使用jmp printMessage
( Tail Call )。 當達到printMessage
的ret
時,控制將返回到調用sample_assembly_function
的函數。 此代碼應該工作:
ENTRY(sample_assembly_function)
mov $10, %edi
jmp printMessage
END(sample_assembly_function)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.