簡體   English   中英

如何從我在 MASM 匯編程序中調用的 C function 調用 printf?

[英]How to call printf from a C function that I call in the MASM assembler?

I have a C file called C.c and for now in that file I have one function that compares two numbers and saves the greater number to the register eax.

我需要幫助創建第二個 function,它將在內部調用printf並打印一些文本。 如何在我可以從 MASM 匯編程序調用的 C 中添加對printf的支持?

我的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;
}

您需要鏈接到適當的庫(例如msvcrt.lib )並且您需要知道函數的導出名稱。 要檢測我使用的名稱diminGUI

C 函數的調用約定稱為“cdecl”。 arguments 被壓入堆棧,調用后必須調整堆棧。 如果您將 function 聲明為PROTO C INVOKE您可以讓 MASM 使用 INVOKE 來完成這項工作。

例子:

測試.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

讓我們將 output function 添加到 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

我剛剛從 MASM for x86 附帶的教程/控制台/演示 1 開始解決這個問題。 它說使用下拉“項目”菜單中的控制台選項進行編譯。 它工作得很好,我認為它接近最低限度的開始:

.486                                    ; create 32 bit code
.model flat, stdcall                    ; 32 bit memory model
option casemap :none                    ; case sensitive


include \masm32\include\windows.inc     ; always first
include \masm32\macros\macros.asm       ; MASM support macros

include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\msvcrt.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\msvcrt.lib

.code 

start:  

print chr$("Hey, this actually works.",13,10)

mov         eax, 0
mov         ebx, 0
printf("%d\t %d\t\n", eax, ebx);

mov         eax, 100
mov         ebx, 100
printf("%d\t %d\t\n", eax, ebx);

mov         eax, 100
mov         ebx, 100
add eax, ebx
printf("%d\t %d\t\n", eax, ebx)

exit
end start

我在這里使用 printf 從寄存器打印。 我從中發現 printf 本身會影響寄存器 EAX、ECX 和 EDX,因為如果在 printf 語句通過之前未重新加載 eax,則add將不會給出正確的結果。 (在調試器中單步執行並觀察寄存器值的變化時,您也可以看到這一點)。

這將從 eax 和 ebx 寄存器打印,但您可以按照 C 語法打印任何您想要的內容。 重要的是包括這兩行:

include \masm32\include\msvcrt.inc
includelib \masm32\lib\msvcrt.lib

您需要同時包含它們; .inc定義了printf() C 風格的宏,因此沒有它,語法將無法工作。

rkhb 對這個問題的回答顯示了如何手動聲明printf並像任何其他 function 一樣使用標准 MASM INVOKE調用它,或者甚至自己推 args 並call printf而不做任何魔術。 在這種情況下,您只需要.lib

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM