从外部解析未定义的符号

时间:2017-09-04 05:22:21

标签: visual-studio assembly x86 masm masm32

装配中的初级水平。

我在Visual Studio中收到的错误是:

1> File2.asm(27):错误A2006:未定义的符号:sprintf

1> File2.asm(28):错误A2006:未定义的符号:MessageBoxA

文件1处理计算

文件2是将结果打印到窗口的内容。

句柄打印指令的行是:

Fungeable<Blarg>

我错误的原因是什么?

是因为sprintf是C函数吗?

File1.asm

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

File2.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

1 个答案:

答案 0 :(得分:0)

您正在使用来自MSVCRT.lib的函数sprintf,它是一个C库,其导出名称为prefixed by an underscore。因此它_sprintf代替sprintf

函数MessageBox包含在user32.lib中,你没有包含它,因此链接器找不到它。

user32.lib中的函数wsprintfsprintf非常相似,所以如果你想节省空间并减小文件的大小,你可以使用那个代替。

sprintfwsprintf都使用C calling convention(与.model flat,stdcall行中默认设置的STDCALL约定相反)。

  

注意重要的是要注意wsprintf使用C调用约定(_cdecl),而不是标准调用(_stdcall)调用约定。因此,调用进程有责任从堆栈中弹出参数,并且参数从右向左推送到堆栈中。在C语言模块中,C编译器执行此任务。

但是INVOKE(更确切地说:its PROTO directive)会照顾到这一点,所以现在不要担心。

要修复错误,请将这些行更改/添加到您的代码中:

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