我有一个基本的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;
TCHAR FilePathPattern[] = TEXT("C:\\Users\\Bloodsucker94\\Desktop\\TestASM\\*.txt");
if ((hFile = FindFirstFile(FilePathPattern, &findFileData)) == INVALID_HANDLE_VALUE)
_tprintf(TEXT("FindFirstFile() failed with code %d\n"), GetLastError());
else {
_tprintf(TEXT("hFile=%d, addr=0x%08X\n"), hFile, &findFileData);
do {
TCHAR beginPath[] = TEXT("C:\\Users\\Bloodsucker94\\Desktop\\TestASM\\");
lstrcat(beginPath, findFileData.cFileName);
_tprintf(TEXT("%s\n"), beginPath);
//printf("%s\n", beginPath);
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
includelib \masm32\lib\crtdll.lib
_tprintf PROTO C :VARARG
.data
FolderPath TCHAR "C:\Users\Bloodsucker94\Desktop\TestASM\*.txt", 0
BeginFolderPath TCHAR "C:\Users\Bloodsucker94\Desktop\TestASM\", 0
FileName TCHAR "ta_mere.txt", 0
LstrcatFailed BYTE "lstrcat failed", 0
FormatPrintString BYTE "%s\n", 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 ?
FinalFilePath LPTSTR ?
.code
start:
;--------------------------------------------------------
invoke FindFirstFile, ADDR FolderPath, \
ADDR findFileData
mov hFile, eax
.IF hFile == INVALID_HANDLE_VALUE
invoke GetLastError
mov ErrorCode, eax
printf("%d\n", ErrorCode)
jmp _quit
.ENDIF
;--------------------------------------------------------
_loop:
invoke lstrcat, ADDR BeginFolderPath,
ADDR findFileData.cFileName
mov FinalFilePath, eax
.IF FinalFilePath == NULL
invoke MessageBox, NULL, \
ADDR LstrcatFailed, \
ADDR LstrcatFailed, \
MB_OK
.endif
;invoke crt_printf, ADDR FormatPrintString, \
; findFileData.cFileName
invoke MessageBox, NULL, \
ADDR FinalFilePath, \
ADDR FinalFilePath, \
MB_OK
;--------------------------------------------------------
invoke FindNextFile, hFile, \
ADDR findFileData
.IF eax == NULL
jmp _quit
.ELSE
jmp _loop
.ENDIF
;--------------------------------------------------------
_quit:
invoke ExitProcess, 0
end start
编译工作完美。 lstrcat函数也不会失败。但在执行时,消息框显示字符串“-O @”。当我想用printf而不是_tprintf打印时,我注意到c ++程序中的行为相同(因为打印TCHAR Windows类型不适用于printf)。也许问题来自MessageBox函数或者TCHAR类型可能不是好的。只有c ++程序才有效。我输了。
有人可以帮助我吗?
提前感谢您的帮助。
答案 0 :(得分:0)
首先,您对lstrcat
的调用将覆盖BeginFolderPath
之后的内存。因此,FileName
的值将会被覆盖,如果文件名很长,则无法确定该调用会破坏数据段的哪些部分。缓冲区溢出不是lstrcat
唯一可能出现的问题。请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/ms647487(v=vs.85).aspx
您可以考虑在调试器中运行它并在调用lstrcat
后查看内存。
此外,您正在为您的字符串混合TCHAR
和BYTE
,这有点令人困惑。我不清楚你是否希望这个程序使用Unicode或ANSI字符串。正如它目前所写,这是不可能的。 TCHAR
是这个程序中的一个字节,还是一个单词?如果这是一个单词,那么您需要调用MessageBoxW
。
设置输出汇编列表文件的编译器开关并编译C ++程序将具有指导意义。看一下生成的汇编代码。