I am writing a 32-bit C kernel and I tried to call a function that I wrote in assembly.
So I wrote an assembly file containing the function myfunc
and then I wrote the kernel which defined myfunc
as a global variable and I linked them together so I can use it in my C code.
It worked fine, but when I tried to call it, it caused a triple fault.
However, if I use inline assembly instead,
asm("call myfunc");
It does the job.
Also notice that the disassembly for asm("call myfunc");
and for myfunc();
aren't similar:
The disassembly when using myfunc()
:
00000000 <kmain>:
0: f3 0f 1e fb endbr32
4: 53 push ebx
5: 83 ec 08 sub esp,0x8
8: e8 fc ff ff ff call 9 <kmain+0x9>
d: 81 c3 02 00 00 00 add ebx,0x2
13: e8 fc ff ff ff call 14 <kmain+0x14>
18: f4 hlt
19: 83 c4 08 add esp,0x8
1c: 5b pop ebx
1d: c3 ret
The disassembly when using asm("call myfunc");
:
00000000 <kmain>:
0: f3 0f 1e fb endbr32
4: e8 fc ff ff ff call 5 <kmain+0x5>
9: f4 hlt
a: c3 ret
Here's how I build it:
nasm -f elf32 kernel/klink.asm -o klink.o
gcc -c kernel/main.c -m32 -nostdlib -nodefaultlibs -O1 -fno-builtin
ld -m elf_i386 -T link.ld -o KERNEL klink.o main.o
objcopy --dump-section .text=KERNEL.SYS KERNEL
link.ld
:
OUTPUT_FORMAT(elf32-i386)
ENTRY(kmain)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
}
The kernel (main.c
):
void kmain() {
extern void myfunc();
myfunc(); //Here it causes a triple fault.
//asm("call myfunc"); //But this works fine.
asm("hlt");
}
And this is the assembly file that contains the function (klink.asm
):
[BITS 32]
SECTION .text
GLOBAL start ;define start as a global variable
GLOBAL myfunc ;also myfunc
jmp start ;jump straight into start
myfunc:
;idk what to write here... just some code :)
EXTERN kmain ;define kmain as an external variable
start:
jmp kmain ;jump into kmain