Winapi 如何将带有ReadFile的文件读取到NASM x86程序集中的堆栈上?

Winapi 如何将带有ReadFile的文件读取到NASM x86程序集中的堆栈上?,winapi,assembly,x86,nasm,Winapi,Assembly,X86,Nasm,我用OpenFile打开了一个文件,并用GetFileSize获得了它的大小。我希望使用ReadFile并将堆栈用作它所需的缓冲区,在堆栈上分配足够的空间,使其具有从GetFileSize返回的文件大小。当我运行这个时,我没有得到任何输出 这是我的密码 extern GetStdHandle 外部GetModuleFileNameA 外部开放文件 外部读取文件 外部写入文件 外把手 外部获取文件大小 外部退出过程 导入GetStdHandle内核32.dll 导入GetModuleFileNam

我用OpenFile打开了一个文件,并用GetFileSize获得了它的大小。我希望使用ReadFile并将堆栈用作它所需的缓冲区,在堆栈上分配足够的空间,使其具有从GetFileSize返回的文件大小。当我运行这个时,我没有得到任何输出

这是我的密码

extern GetStdHandle
外部GetModuleFileNameA
外部开放文件
外部读取文件
外部写入文件
外把手
外部获取文件大小
外部退出过程
导入GetStdHandle内核32.dll
导入GetModuleFileNameA kernel32.dll
导入OpenFile kernel32.dll
导入ReadFile kernel32.dll
导入WriteFile kernel32.dll
导入CloseHandle内核32.dll
导入GetFileSize kernel32.dll
导入ExitProcess内核32.dll
全球..开始
段。代码使用32
…开始:
;正在设置堆栈。。。
推ebp
电动汽车
;获取控制台的标准输出
推德沃德-11
调用[GetStdHandle]
mov dword[hStdOut],eax
;获取文件路径。。。
推送dword文件路径
推送dword 0
调用[GetModuleFileNameA]
;输出文件路径
;不会显示在控制台上,但如果将其转储到文件中
;编辑它,它就在那里。。。
;推送dword 0
;按dword字节读
;推送dword 128;OpenFile的最大路径大小。。。
;推送dword文件路径
;推送dword[hStdOut]
;调用[写入文件]
;正在打开文件并获取句柄。。。
推送dword 0
结构的推德沃德
推送dword文件路径
mov dword[hself文件]
;正在获取文件大小。。。
推送dword 0
推送dword HSELF文件
调用[GetFileSize]
mov dword[fSize],eax
;正在堆栈上分配数据。。。
子esp,fSize
;正在读取文件。。。
推送dword 0
按dword字节读
推送dword fSize
推德沃德ebp;ebp还是esp?
推送dword[hself文件]
调用[ReadFile]
;正在输出读取的文件。。。
推送dword 0
按dword字节读
推送dword fSize
推德沃德ebp;ebp还是esp?
推送dword[hStdOut]
调用[写入文件]
;正在关闭文件句柄。。。
推送dword HSELF文件
呼叫[关闭手柄]
;正在清理堆栈。。。
电除尘器
流行ebp
异或eax,eax
推送eax
呼叫[出口流程]
段.数据
第2部分:bss
hst输出resd 1
hself文件resd 1
字节读取resd 1
结构resb 136;ofstruct的大小(以字节为单位)
fsizeresd1
文件路径resb 128;OpenFile将允许的最大路径

我做错了什么?

malloc?当有内存函数是Windows的一部分时,为什么要链接到C库

除了代码中的所有错误之外,您是否意识到您正在尝试打开一个可执行文件并将内容打印到控制台?你不能这样做(当然你可以,但你不会得到任何漂亮的东西),因为前任包含不可打印的字符,你会在屏幕上看到很多垃圾

下面是一些示例代码,它将在exes目录中打开一个文本文件,获取大小,分配一些内存来保存文件,读取文件,并将内容显示到控制台

这里绝对不涉及错误检查,您当然会在普通应用程序中添加错误检查

创建一个名为test.txt的文本文件,并将其保存在exes目录中。您可以使用此测试所需的任何文本填充此文件。我选择使用培根lorem ipsum生成器,因为我喜欢培根:-)


你做了什么调试?您的代码检查返回值是否有错误一点都不清楚。您的代码缺少部分,复制粘贴错误
mov-dword[hself-file]
没有意义,您可能也缺少了一个
调用[OpenFile]
。PS:学习使用调试器。另外,对于
GetFileSize
您可能希望
push dword[hself file]
而不是
push dword hself file
。您应该在从中减去ESP值后,而不是EBP值后,再推送ESP值。这意味着您需要在执行更多推送参数之前保存该值,因为这会改变ESP。从ESP中减去不会改变EBP。ESP指向堆栈顶部(堆栈上最低的有效地址),因此通过从ESP中减去而分配的缓冲区就是ESP指向的堆栈顶部。然而,事情并没有那么简单。如果文件大小大于4096字节(虚拟内存页的大小),代码可能会失败。有没有办法解决分页问题?其他程序在将大文件加载到内存中时似乎没有问题。您不应该将大文件加载到堆栈中。分配堆内存。简单、干净的代码,信息量大。虽然我非常喜欢自学,但这是一个正确的方向,我迫不及待地想采用这段代码并使用它。你把.text部分放在最后的方式很好。。。
%define STD_OUTPUT_HANDLE -11
%define OPEN_EXISTING 3
%define NULL 0
%define HEAP_ZERO_MEMORY 8
%define FILE_READ_DATA 1

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
section .bss
hConOut         resd 1
lpBytesWritten  resd 1
hSelfFile       resd 1
hHeap           resd 1
lpFileSize      resd 1
hReadBuf        resd 1

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
section .data
szTestFile      db 'test.txt', 0
szCRLF          db 13, 10 

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global Start
section .text
Start:    
    call    GetProcessHeap                  ; get handle to apps heap
    mov     [hHeap], eax        

    push    STD_OUTPUT_HANDLE               ; um, self explanitory
    call    GetStdHandle
    mov     [hConOut], eax

    push    NULL
    push    NULL
    push    OPEN_EXISTING
    push    NULL
    push    0
    push    FILE_READ_DATA
    push    szTestFile
    call    CreateFileA                     ; Let's open the damn file
    mov     [hSelfFile], eax   

    push    NULL
    push    eax
    call    GetFileSize                     ; well, get the size of file to read
    add     eax, 1
    mov     [lpFileSize], eax

    push    eax
    push    HEAP_ZERO_MEMORY
    push    dword [hHeap]
    call    HeapAlloc                       ; now allocate some memory to hold contents
    mov     [hReadBuf], eax

    push    NULL
    push    lpBytesWritten
    push    dword [lpFileSize]
    push    dword [hReadBuf]
    push    dword [hSelfFile]
    call    ReadFile                        ; slurp it into memory

    push    dword [hSelfFile]
    call    CloseHandle                     ; don't need anymore

    push    NULL
    push    lpBytesWritten 
    push    dword [lpFileSize]
    push    dword [hReadBuf]
    push    dword [hConOut]
    call    WriteFile                       ; print to console

    push    NULL
    push    lpBytesWritten 
    push    2
    push    szCRLF                          
    push    dword [hConOut]
    call    WriteFile                       ; "display carrage return/linefeed"

    push    NULL
    push    hReadBuf
    call    HeapFree                        ; free the our buffer memory

    push    0
    call    ExitProcess

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
extern GetStdHandle
extern CreateFileA
extern ReadFile
extern WriteFile
extern CloseHandle
extern GetFileSize
extern ExitProcess
extern GetProcessHeap
extern HeapAlloc
extern HeapFree