Jan Weber
Jan Weber

Reputation: 137

MinGW Win32 + nasm: "undefined reference"

I am currently developing an OS for learning purposes, and it's been working fine until now. Then I tried to call an assembler function, compiled with nasm, -fwin32, from C code, but all I got was an "undefined reference" error. I have created a small example in pure assembler, which has the same problem, but is easily understandable and way smaller: 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 the error:

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

To extend 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!

Upvotes: 3

Views: 2374

Answers (2)

Gene
Gene

Reputation: 46960

In my MinGW setup you need a section directive before the code.

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

Then assemble to win32 format:

nasm -fwin32 foo.asm -o foo.o

Now you can check that testfunc is there:

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

The T means text section global, so we're good to go.

Note I'd avoid naming anything test since this is a shell command. This can cause endless grief.

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

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

Then to build an executable let gcc do the heavy lifting because ld sometimes needs arcane arguments.

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

Upvotes: 3

Gunner
Gunner

Reputation: 5884

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

Your asm files should look like the following:

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

Upvotes: 2

Related Questions