Resolving undefined symbols externally

1.1k Views Asked by At

Beginner level in Assembly.

The error I receive in Visual Studio is:

1>File2.asm(27): error A2006: undefined symbol : sprintf

1>File2.asm(28): error A2006: undefined symbol : MessageBoxA

File 1 is what handles calculations

File 2 is what prints result to a window.

The line the handles print instructions is:

   invoke sprintf, addr szBuf, offset $interm, eax, edx
   invoke MessageBoxA, 0, addr szBuf, offset _title, 0
   invoke ExitProcess, 0

What am I doing wrong to the cause it not to build?

Is it because sprintf is a C function?

File1.asm

.386
.model flat, stdcall
option casemap :none  

 PUBLIC squareroot
 PUBLIC szBuf
 include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\msvcrt.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib

.data
  _title db "Result",13,10,0
  $interm db "%0.4f","+","%0.5f",13,10,0
   Aval REAL8 1.000
   Bval REAL8 -2.000
   Cval REAL8 19.000
   _fourval REAL8 4.000
   $Tvalueinc REAL4 1.0,2.00,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0
   $sampleval real10 4478784.0
   $Powercounter dd ?
   squareroot dq ?
   $prevCW dw ?
   $Tagword dd ?
   $INT1 dq ?


  EXTERN Finished:PROC


.code
szBuf:

add eax,4

fstcw $prevCW
fwait
fld Bval ;  [loads first instance of b]]
fmul Bval ; [b*b = b^2]
fld Aval ;[Load a (a*c)]
fmul Cval ;(a*c)
fmul _fourval ;[4*a*c]
fsubp;[b^2-4*a*c]
ftst ;compare ST(0) with 0.0
fstsw ax ;[store camparison results in ax]
sahf ;transfer flags from AH register
mov ecx, 0004h


jb _negative ;jump if <0
fsqrt ;sqrt(b^2-4*a*c)



_negative:
fchs 
fsqrt
fld $sampleval
xor eax,eax
$repeat:


inc eax
push eax
mov ax, $prevCW
push eax
fldcw [esp]
fld $Tvalueinc[ecx]
fdivp
fld st(0)
FRNDINT
fcomp
fstsw ax
Sahf
fnstenv    [ebx-10h]
movzx   eax, word ptr [ebx-10h + 8h]
fldcw $prevCW
pop eax
pop eax

jz $repeat
dec eax
cmp eax, $Powercounter
add ecx, 0004h
mov eax, dword ptr squareroot
mov edx, dword ptr squareroot[0004h]
jmp Finished
END szBuf

File2.asm

.386
.model flat,stdcall
option casemap:none

PUBLIC Finished
PUBLIC ExitProcess

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\msvcrt.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib

.data
   _title db "Result",13,10,0
   $interm db "%0.4f","+","%0.5f",13,10,0


.code

Finished:  




   invoke sprintf, addr szBuf, offset $interm, eax, edx
   invoke MessageBoxA, 0, addr szBuf, offset _title, 0
   invoke ExitProcess, 0

END
1

There are 1 best solutions below

0
On

You are using the function sprintf from MSVCRT.lib, which is a C library, and its exported name is prefixed by an underscore. Hence it's _sprintf instead of sprintf.

The function MessageBox is contained in user32.lib which you didn't incluce, so the linker could not find it.

There's also the function wsprintf in user32.lib which is quite similar to sprintf, so if you want to save space and decrease the size of the file you can use that one instead.

sprintf and wsprintf both use the C calling convention (contrary to the STDCALL convention set as default in the .model flat,stdcall line).

Note It is important to note that wsprintf uses the C calling convention (_cdecl), rather than the standard call (_stdcall) calling convention. As a result, it is the responsibility of the calling process to pop arguments off the stack, and arguments are pushed on the stack from right to left. In C-language modules, the C compiler performs this task.

But INVOKE(more precise: its PROTO directive) does take care of that so don't worry now.

To fix the errors change/add these lines to your code:

include     \masm32\include\user32.inc
includelib  \masm32\lib\user32.lib
...
invoke _sprintf, addr szBuf, offset $interm, eax, edx