MinGW Win32 + nasm: "undefined link"

I am currently developing an OS for educational purposes and it still works. Then I tried to call the assembler function, compiled with nasm, -fwin32

, from C code, but all I got was an "undefined reference" error. I created a small example in pure assembler that has the same problem, but is easy to understand and small: It includes two files:

test.asm:

[bits 32]
global _testfunc
_testfunc:
    ret

test2.asm:

[bits 32]
extern _testfunc
global _testfunc2
_testfunc2:
    call _testfunc
    ret

      

Here is my compiler / linker script (using windows batch files):

nasm.exe -f win32 test.asm -o test.o
nasm.exe -f win32 test2.asm -o test2.o
ld test.o test2.o -o output.tmp

      

This results in an error:

test2.o:test2.asm:(.text+0x1): undefined reference to `testfunc'

      

To expand on the question, the same happens when the function is called from C:

test.c:

extern void testfunc(void);
void start()
{
    testfunc();
}

      

With this linker script:

gcc -ffreestanding -c test.c -o testc.o
nasm.exe -f win32 test.asm -o test.o
ld test.o testc.o -o output.tmp

      

In test.o, test2.o and testc.o it always says _testfunc

, so the error has nothing to do with leading underscores!

+3


source to share


2 answers


In my MinGW setup, you need a directive section

before the code.

; foo.asm
[bits 32]
global _testfunc
section .text
_testfunc:
    ret

      

Then create win32 format:

nasm -fwin32 foo.asm -o foo.o

      

Now you can check what testfunc

is there:

$ nm foo.o
00000000 a .absolut
00000000 t .text
00000001 a @feat.00
00000000 T _testfunc

      



T

means the text section is global, so we're good to go.

Note. I would not name anything test

as it is a shell command. It can cause endless grief.

C function as you showed it, but name the file something else:

// main.c
extern void testfunc(void);
int main(void)
{
    testfunc();
    return 0;
}

      

Then we gcc

do the heavy lifting to create the let executable, because ld

sometimes a secret argument is required.

gcc -ffreestanding main.c foo.o -o main

      

+3


source


Your missing something is important, your code is not in the code section!

Your asm files should look like this:

test.asm



global _testfunc

section .text       ; <<<< This is important!!!        
; all code goes below this!                                                  
_testfunc:

    ret

      

test2.asm

extern _testfunc
global _testfunc2

section .text       ; <<<< Again, this is important!!!                                                          
_testfunc2:
    call    _testfunc
    ret

      

+2


source







All Articles