如何从我在MASM汇编程序中调用的C函数调用printf?

时间:2015-04-15 15:20:13

标签: c assembly masm

我有一个名为C.c的C文件,现在在该文件中我有一个函数比较两个数字并将更大的数字保存到寄存器eax。

我需要帮助创建第二个函数,它将调用printf并打印一些文本。如何在C中添加对printf的支持,我可以从MASM汇编程序调用它?

我的masm文件:

    TITLE MASM Template (main.asm)
.386
.model FLAT
.stack 4096

WriteString PROTO stdcall
ReadChar PROTO stdcall
Crlf PROTO stdcall
ExitProcess PROTO stdcall:DWORD
greater PROTO C :DWORD, :DWORD


.data
PorukaZaIspis db "Poruka za ispis", 0

.code
_main PROC

push 8
push 3
call greater


call Crlf
mov edx, OFFSET PorukaZaIspis
call WriteString
call ReadChar
Invoke ExitProcess, 0
_main ENDP
END _main

END

我的C.c文件:

int greater(int a, int b) {
if ( a > b)
return a;
else 
return b;
}

1 个答案:

答案 0 :(得分:0)

您需要链接到适当的库(例如msvcrt.lib),并且您需要知道函数的导出名称。要检测我使用的名称dumbinGUI

C函数的调用约定称为" cdecl"。参数被压入堆栈,并且必须在调用后调整堆栈。如果您将函数声明为INVOKE,则可以使用PROTO C让MASM完成这项工作。

示例:

<强> TEST.ASM:

.686
.model FLAT

INCLUDELIB msvcrt.lib
printf PROTO C, :VARARG
exit PROTO C, :DWORD

; Functions in C.c:
greater PROTO C :DWORD, :DWORD          ; Declaration of greater (int,int)
hello PROTO C                           ; Declaration of hello (void)

.data
fmt db "%s %u", 10, 0                   ; '10': printf of msvcrt.dll doesn't accept "\n"
PorukaZaIspis db "Message from ASM: ", 0

.code
_main PROC
    invoke greater, 8, 3
    call output                         ; "Message from ASM ..."
    invoke hello                        ; "Message from C ..."
    invoke exit, 0
_main ENDP

output PROC                             ; ARG: EAX
    invoke printf, OFFSET fmt, OFFSET PorukaZaIspis, eax
    ret
output ENDP

END _main

让我们将输出函数添加到C文件中:

<强> C.C:

#include <stdio.h>

void hello ()
{
    puts ("Message from C: hello");
}

int greater(int a, int b)
{
    if ( a > b)
        return a;
    else
        return b;
}

使用以下批处理文件:

@ECHO OFF
SET VS_PATH=<Full\Path\to\Visual Studio\e.g.\C:\Program Files\Microsoft Visual Studio 10.0>

SET PATH=%VS_PATH%\VC\bin
SET LIB=%VS_PATH%\VC\lib
SET INCLUDE=%VS_PATH%\VC\include

SET CALLER=test.asm
SET CALLEE=C.c
SET TARGET=test.exe

echo cl_first
del %TARGET%
call :cl_first %CALLER% %CALLEE% %TARGET%
if exist %TARGET% %TARGET%

echo.
echo ml_first
del %TARGET%
call :ml_first %CALLER% %CALLEE% %TARGET%
if exist %TARGET% %TARGET%

goto :eof

:cl_first
cl /nologo /c %2
ml /nologo /Fe%3 %1 %~n2.obj /link /nologo
goto :eof

:ml_first
ml /nologo /c %1
cl /nologo /Fe%3 %~n1.obj %~n2.c /link /nologo
goto :eof