1

アセンブラでカーネルモジュールを書いてみます。一度にグローバル変数が必要でした。.data (または .bss) セクションで dword を定義し、init 関数で var に 1 を追加します。私のプログラムは正常に作成されますが、insmod sey me:

$ sudo insmod ./test.ko
insmod: ERROR: could not insert module ./test.ko: Invalid module format

それはnasmの私のアセンブラコードです:

[bits 64]

global init
global cleanup

extern printk

section .data
    init_mess db "Hello!", 10, 0
    g_var dd 0

section .text

init:
    push rbp
    mov rbp, rsp

    inc dword [g_var]

    mov rdi, init_mess
    xor rax, rax
    call printk

    xor rax, rax
    mov rsp, rbp
    pop rbp
    ret

cleanup:
    xor rax, rax
    ret

Cコードに追加して書くと、すべてうまくいきます:

static i = 0;
static int  __init main_init(void)    { i++; return init(); }

しかし、これobjdump -d test.koで私のために非常に厳しいコードを書いてください:

0000000000000000 <init_module>:
   0:   55                      push   %rbp
   1:   ff 05 00 00 00 00       incl   0x0(%rip)        # 7 <init_module+0x7>
   7:   48 89 e5                mov    %rsp,%rbp
   a:   e8 00 00 00 00          callq  f <init_module+0xf>
   f:   5d                      pop    %rbp
  10:   c3                      retq  

これはどういう意味ですか (0x0(%rip) を含む)? どうすればメモリにアクセスできますか? 助けてください :) (私のシステムは archlinux x86_64 です)

モジュールを正しく作成するための私のCコード:

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

MODULE_AUTHOR("Actics");
MODULE_DESCRIPTION("Description");
MODULE_LICENSE("GPL");

extern int init(void);
extern int cleanup(void);

static int  __init main_init(void)    { return init(); }
static void __exit main_cleanup(void) { cleanup(); }

module_init(main_init);
module_exit(main_cleanup);

そして私のMakefile:

obj-m := test.o
test-objs := inthan.o module.o
KVERSION = $(shell uname -r)
inthan.o: inthan.asm
    nasm -f elf64 -o $@ $^

build:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
4

2 に答える 2

3

カーネル モードは、アドレス空間の「負の」(つまり、トップ) 部分にあり、32 ビットの絶対アドレスは使用できません (符号拡張されていないため)。お気づきのように、gcc は rip-relative アドレスを使用して、現在の命令ポインターからのオフセットを与えるこの問題を回避します。ディレクティブを使用して、nasm に同じことをさせることができますDEFAULT RELnasm ドキュメントの関連セクションを参照してください。

于 2012-12-04T23:33:30.460 に答える
1

いつでもインラインアセンブリを使用できます

 asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0"             \
 54             : "=&r" (flag), "=r" (roksum)                               \
 55             : "1" (addr), "g" ((long)(size)),                           \
 56               "rm" (limit));      
于 2012-12-04T20:52:52.007 に答える