如何在汇编中正确调用 64 位 Windows API

Eri*_*man 1 windows 64-bit assembly nasm

使用 NASM 和 Mingw-w64 我一直在尝试运行以下程序,该程序应该使用 Windows API 将消息打印到屏幕上。它运行,但控制台上没有显示任何内容,并导致对内存位置的无效访问(错误代码 0x3e6h)。为什么会这样,我怎样才能让程序正常运行?

global main
extern ExitProcess
extern GetStdHandle
extern WriteFile

section .text
main:
    mov     rcx,                  0fffffff5h
    call    GetStdHandle

    mov     rcx,                  rax
    mov     rdx,                  NtlpBuffer
    mov     r8,                   NtnNBytesToWrite
    mov     r9,                   NtlpNBytesWritten
    mov     dword [rsp - 04h],    00h
    call    WriteFile
ExitProgram:
    mov     rcx,                  00h
    call    ExitProcess

section .data
NtlpBuffer:        db    'Hello, World!', 00h
NtnNBytesToWrite:  dd    0eh

section .bss
NtlpNBytesWritten: resd  01h
Run Code Online (Sandbox Code Playgroud)

编译者

nasm -f win64 test.asm
gcc -s -o test.exe test.obj
Run Code Online (Sandbox Code Playgroud)

Jes*_*ter 5

[rsp-04h]在堆栈指针下方寻址,这是一个坏主意。不管你在那里写什么,call反正都会被覆盖。看起来您需要复习一下调用约定的知识。必须为寄存器中的 4 个参数分配影子空间,并且必须将更多参数放置在它们之上。

此外,要写入的字节数应该是实际数字,而不是指针。

global main
extern GetStdHandle
extern WriteFile

section .text
main:
    mov     rcx, 0fffffff5h
    call    GetStdHandle

    mov     rcx, rax
    mov     rdx, NtlpBuffer
    mov     r8, [NtnNBytesToWrite]
    mov     r9, NtlpNBytesWritten
    sub     rsp, 40
    mov     dword [rsp + 32], 00h
    call    WriteFile
    add     rsp, 40
ExitProgram:
    xor     eax, eax
    ret

section .data
NtlpBuffer:        db    'Hello, World!', 00h
NtnNBytesToWrite:  dq    0eh

section .bss
NtlpNBytesWritten: resd  01h
Run Code Online (Sandbox Code Playgroud)