News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

External symbol error when linking multiple modules

Started by jaredH, May 01, 2010, 08:26:45 PM

Previous topic - Next topic

jaredH

I imagine this question has come up before, although I did search around a bit, both online and this forum but couldn't seem to immediately find anything.

I'm trying to learn how to use multiple modules for when I start working on some slightly larger assembly projects. Coming from a C/C++ background, I have been used to compiling each .c file into an object file, and then linking them all together into an executable. I'm trying to basically do the same thing here, but my main module gives an external symbol error when trying to call a procedure defined in another module.

My main module (test.asm):

.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

externdef TestFunction:near

.data
msg db "Hello, world!",0
msg_caption db "Test",0

.code

start:
  mov eax,MB_OK
  push eax
  lea eax,msg_caption
  push eax
  lea eax,msg
  push eax
  xor eax,eax
  push eax
  call MessageBox
 
  call TestFunction

  mov eax,0
  push eax
  call ExitProcess
end start


and then the other module (proc.asm):

.386
.model flat,stdcall

.code

TestFunction proc
  push ebp
  mov ebp, esp

  mov esp, ebp
  pop ebp
  ret 0
TestFunction endp
end


I am compiling everything like so:

ml /c /coff test.asm
ml /c /coff proc.asm

which both work fine. This, however doesn't:

link /SUBSYSTEM:console /LIBPATH:f:\masm32\lib /ENTRY:start test.asm proc.asm

giving the following error:

Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

test.obj : error LNK2001: unresolved external symbol _TestFunction
test.exe : fatal error LNK1120: 1 unresolved externals

Am I missing something obvious here?

redskull

http://en.wikipedia.org/wiki/Name_mangling

Basically, either add a 'stdcall' or rename your function with the underscore
Strange women, lying in ponds, distributing swords, is no basis for a system of government

jaredH

Well, I have the stdcall up near the top of both modules, if that is what you are referring to. And, I already tried adding an underscore to the procedure name in 'proc.asm' and re-compiling it, but it still gave the same error.

qWord

I recommend you to use PROTO instead of EXTERNDEF:
TestFunction PROTO
FPU in a trice: SmplMath
It's that simple!

jaredH

Thanks, qWord. Using the PROTO method worked fine.

clive

Yes, just tested that, qWord beat me to the post.

Also you might want to specify OBJ files in the LINK command line rather than ASM

ml -c -coff -Fl test.asm
ml -c -coff -Fl proc.asm
link /SUBSYSTEM:console /LIBPATH:\masm32\lib /ENTRY:start test.obj proc.obj


With "externdef TestFunction:near" test.obj looks like this

Disassembly

00000000                    _start:
00000000 B800000000             mov     eax,0
00000005 50                     push    eax
00000006 8D053E000000           lea     eax,[3Eh]
0000000C 50                     push    eax
0000000D 8D0530000000           lea     eax,[30h]
00000013 50                     push    eax
00000014 33C0                   xor     eax,eax
00000016 50                     push    eax
00000017 E8E4FFFEEF             call    _MessageBoxA@16
0000001C E8DFFFFDEF             call    _TestFunction
00000021 B800000000             mov     eax,0
00000026 50                     push    eax
00000027 E8D4FFFCEF             call    _ExitProcess@4


With "TestFunction PROTO" test.obj looks like this

Disassembly

00000000                    _start:
00000000 B800000000             mov     eax,0
00000005 50                     push    eax
00000006 8D053E000000           lea     eax,[3Eh]
0000000C 50                     push    eax
0000000D 8D0530000000           lea     eax,[30h]
00000013 50                     push    eax
00000014 33C0                   xor     eax,eax
00000016 50                     push    eax
00000017 E8E4FFFEEF             call    _MessageBoxA@16
0000001C E8DFFFFDEF             call    _TestFunction@0
00000021 B800000000             mov     eax,0
00000026 50                     push    eax
00000027 E8D4FFFCEF             call    _ExitProcess@4


While proc.obj looks like this

Disassembly

00000000                    _TestFunction@0:
00000000 55                     push    ebp
00000001 8BEC                   mov     ebp,esp
00000003 8BE5                   mov     esp,ebp
00000005 5D                     pop     ebp
00000006 C3                     ret
It could be a random act of randomness. Those happen a lot as well.

jaredH

Yes, excellent point. In my haste to post this in order to get an answer, I obviously typed out the link line incorrectly.