簡體   English   中英

在 linux 內核中混合匯編和 C 函數 - x64 模式

[英]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、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 )。 當達到printMessageret時,控制將返回到調用sample_assembly_function的函數。 此代碼應該工作:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM