2

I am learning assembly language and I create a simple linux kernel module to try how to call an assembly function from module, which in turns call a C function. The code compiles fine. However, when I try to insert the module, it causes kernel crash. I get the idea from this post: Calling C functions from x86 assembly language. I am wondering whether anybody can help me understand why it doesn't work.

The first is assembly code:

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

The second file is sample module file:

#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);

And finally this is 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
Jester
  • 56,577
  • 4
  • 81
  • 125
iceheart
  • 33
  • 7
  • 3
    The x64 calling convention is not at all the same as the x86 calling convention. Maybe take a look at https://stackoverflow.com/a/28601779/12711 and/or https://cs.nyu.edu/courses/fall11/CSCI-GA.2130-001/x64-intro.pdf – Michael Burr Feb 06 '18 at 01:36
  • 1
    I agree with Michael and one other obvious issue is that you push an 8 byte value and then only adjust RSP by 4 after (and not 8) – Michael Petch Feb 06 '18 at 01:51
  • 1
    You are definitely going to need a debugger when you're just learning asm. You can learn *much* more from seeing register values and single-stepping than you can from just a crash. https://www.kernel.org/doc/html/v4.13/dev-tools/kgdb.html – Peter Cordes Feb 06 '18 at 02:52
  • Thanks for all your suggestion. There are some good reference points! @MichaelPetch Please see my comments to your answer. Thanks. – iceheart Feb 06 '18 at 05:18

1 Answers1

2

When using the Linux 64-bit System V ABI calling convention you pass the first 6 integer class or pointer arguments in the registers RDI, RSI, RDX, RCX, R8, and R9. Any remaining parameters are pushed on the stack. The code you linked to in your question is 32-bit code and that uses the Linux i386 System V ABI as a calling convention. That is not compatible with 64-bit code.

Simply do mov $10, %rdi to load the first parameter. Preferably you can do mov $10, %edi. The latter moves the value 10 into EDI but since the target is a 32-bit register the processor automatically zero extends the value across the 64-bit register thus 10 is moved to RDI. The latter is a shorter encoding.

You need a ret instruction to end your assembly language routine. The resulting code should look like:

#include <linux/linkage.h>

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

Since the call is the last thing before ret you can also just jmp printMessage (Tail Call). When the ret in printMessage is reached, control will return to the function that called sample_assembly_function. This code should work:

ENTRY(sample_assembly_function)
mov $10, %edi
jmp printMessage
END(sample_assembly_function)
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • Thanks for the suggestion. It does help me solve the problem. Thanks. I have another question though: I added a new function which just try to add 2 numbers (pass 2 integers as arguments) then printk the result. Exactly same scenario as my original question. The Add2Numbers function is defined in the same C file and then I try to call it from the same assembly file (instead of calling the PrintMessage). However, I get this compiling warning: WARNING: "Add2Numbers" [/home/bob/MixAssemblyAndC/test.ko] undefined! Any suggestion? – iceheart Feb 06 '18 at 05:17
  • @iceheart You could ask a new question with the code that is failing with that error – Michael Petch Feb 06 '18 at 06:09
  • Sorry. It is my fault. I will be more diligent on following up with my own questions. Thanks for the answer. I can accept it as answer for my question. – iceheart Feb 06 '18 at 17:50
  • I guess you are right I may have a typo. It is working now. – iceheart Feb 06 '18 at 17:53