我想在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 ++代码行为。我徒劳地尝试了几种代码组合。
有人可以帮助我吗?
答案 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