0

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

今のところ、ご覧のとおり、ディレクトリ「TestASM」の最初のファイル名を出力したいだけです。実行時に FindFirstFile() はうまく実行されているようで、hFile ハンドルも正しいようです。ただし、すべての印刷呼び出しでメッセージ ボックスにエラー メッセージが表示される理由がわかりません。セグメンテーション違反だと思います。しかし、私は C++ コードの動作を尊重しています。いくつかのコードの組み合わせを試しましたが無駄でした。

誰でも私を助けることができますか?

4

3 に答える 3

1

あなたは宣言するべきですprintf PROTO C :VARARG;

于 2013-03-15T00:05:56.483 に答える
0

コンソールログをウィンドウログ(MessageBox)に置き換えると、機能します。コンソールログが失敗したのはなぜですか?しかし、それは同じデータです!


str$間違っ て使用しています。その定義(masm32 \ macros \ macros.asm)を見ると、DWORDサイズの整数を取り、を使用してその整数の文字列表現(123-> "123"など)を作成しdwtoa、文字列のアドレス。

すでに文字列になっているものを印刷しようとしているので、正しい方法は次のようになります。

print   ADDR findFileData.cFileName


あなたが見ているクラッシュに関しては-あなたの現在のコード(print str$(findFileData.cFileName))で何が起こるかはそれstr$が次のことをするということです:

invoke dwtoa,findFileData.cFileName,ADDR rvstring

MASMがこのinvokeマクロを展開し、引数の前に演算子が見つからない場合、MASMは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最初の引数としてaを期待し、aDWORDを渡すと、からWORD戻るときに不均衡なスタックが発生しdwtoa、あらゆる種類の望ましくない動作(この場合はクラッシュ)が発生する可能性があります。

于 2013-03-15T20:38:42.790 に答える