无法使用MASM打印FindFirstFile WIN32_FIND_DATA结构属性

时间:2013-03-14 23:48:14

标签: assembly masm cpu-registers

我想在MASM中重现下面的C ++代码的行为:

C ++代码:

#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

int                     _tmain(int ac, TCHAR **av)
{
    HANDLE              hFile;
    WIN32_FIND_DATA     findFileData;
    BOOL                retFindNextFile;

    if ((hFile = FindFirstFile(TEXT("C:\\Users\\Bloodsucker94\\Desktop\\TestFolder\\*.txt"), &findFileData)) == INVALID_HANDLE_VALUE)
    else {
        do {
            _tprintf(TEXT("%s\n"), findFileData.cFileName);
            retFindNextFile = FindNextFile(hFile, &findFileData);

        } while (retFindNextFile == TRUE);
    }
    getchar();
    return (EXIT_SUCCESS);
}

MASM代码:

.386
.model                          flat, stdcall
option                          casemap :none

include                         \masm32\include\windows.inc
include                         \masm32\include\kernel32.inc
include                         \masm32\include\masm32.inc
include                         \masm32\include\masm32rt.inc
includelib                      \masm32\lib\kernel32.lib
includelib                      \masm32\lib\masm32.lib
include                         \masm32\include\msvcrt.inc
includelib                      \masm32\lib\msvcrt.lib

.data

FolderPath                      BYTE                        "C:\Users\Bloodsucker94\Desktop\TestASM\*.txt", 0
FindFirstFileError              BYTE                        "FindFirstFile() failed with code %d", 0
FindFirstFileSuccess            BYTE                        "First file found with success - hfile=%d", 0
PrintStructAddr                 BYTE                        "addr=Ox%08X", 0
PrintFileName                   BYTE                        "%s", 0

.data?

hFile                           HANDLE                      ?
findFileData                    WIN32_FIND_DATA             <>
retFindNextFile                 BOOL                        ?
ErrorCode                       DWORD                       ?

.code
start:

    ;--------------------------------------------------------

    invoke  FindFirstFile,      ADDR FolderPath,            \
                                ADDR findFileData

    mov     hFile,              eax

    .IF hFile == INVALID_HANDLE_VALUE
        invoke  GetLastError
        mov     ErrorCode,      eax
        invoke  crt_printf,     ADDR FindFirstFileError,    \
                                ErrorCode
        jmp                     _quit                                
    .ENDIF

    ;--------------------------------------------------------

    mov     ebx,                OFFSET findFileData
    mov     al,                 [ebx].WIN32_FIND_DATA.cFileName

    print   str$(findFileData.cFileName)
    ;print  str$([ebx].WIN32_FIND_DATA.cFileName)
    ;print  str$(al)

    ;INVOKE crt_printf,         ADDR PrintFileName,         \
    ;                           findFileData.cFileName

    ;--------------------------------------------------------

_quit:
    invoke  ExitProcess,        0

end start

目前,正如您所看到的,我只想打印目录中的第一个文件名&#39; TestASM&#39;。在执行时,FindFirstFile()似乎执行得很好,并且hFile句柄似乎也是正确的。但是,我不明白为什么我的所有打印电话都会显示一个显示错误消息的消息框。我认为这是一个细分错误。但我尊重C ++代码行为。我徒劳地尝试了几种代码组合。

有人可以帮助我吗?

3 个答案:

答案 0 :(得分:1)

您应该声明printf PROTO C :VARARG;

答案 1 :(得分:0)

  

我用窗口日志(MessageBox)替换我的控制台日志,它可以工作。我的控制台日志失败的原因但是,这是相同的数据!


您错误地使用了str$。如果你看一下它的定义(masm32 \ macros \ macros.asm),你会发现它的作用是取一个DWORD大小的整数,创建一个整数的字符串表示(例如123 - &gt;“123 “)使用dwtoa,并返回字符串的地址。

由于您正在尝试打印已经是字符串的内容,因此正确的方法是:

print   ADDR findFileData.cFileName


至于您所看到的崩溃 - 当前代码(print str$(findFileData.cFileName))会发生什么,str$将执行以下操作:

invoke dwtoa,findFileData.cFileName,ADDR rvstring

当MASM扩展此invoke宏并且在参数前没有找到ADDR运算符时,它将通过值传递该参数。在这种情况下,它会假设您正在尝试传递findFileData.cFileName的第一个元素,即BYTE(如果您使用的是宽字符串版本,则为WORD)。
所以实际上,这是实际上将作为第一个参数推送到堆栈的内容:

mov al,findFileData.cFileName  ; al is set to the first character in the string
movzx ax,al
push ax   ; can't push bytes on x86 so the byte is extended to a word

由于dwtoa期望DWORD作为第一个参数并且您传递WORD,因此从dwtoa返回时会出现不平衡的堆栈,这会导致各种不受欢迎的行为(在这种情况下是崩溃)。

答案 2 :(得分:0)

这没问题。

mov     ebx,                OFFSET findFileData
lea     eax,                 [ebx].WIN32_FIND_DATA.cFileName

print   eax 

这样做:

INVOKE crt_printf,         ADDR PrintFileName,         \
                           offset findFileData.cFileName

查看此代码与您之间的差异?您需要传递字符串的地址。我们使用lea为第一个执行此操作,并使用printf

的偏移量