0

我以为我已经推送了一些东西而没有弹出它,反之亦然,但我找不到任何错误!我通过调用正确链接的 dll 写入控制台,但我莫名其妙地处于无人区......(地址 0x0000000000000000)

我已经睡了一些觉,而且我确信 API 调用 WriteConsoleA 正在返回。这是我最后一次在打印功能下。

有任何想法吗?

。可执行程序:

extern FreeConsole
extern Sleep
extern ExitProcess

extern print
extern newconsole
extern strlen

section .data BITS 64
        title:  db 'Consolas!',0

        message: db 'Hello, world',0,0

section .text bits 64
global Start
Start:
        mov rcx, title
        call newconsole
        mov rcx, 1000
        call Sleep

        mov rcx, message
        call print

        mov rcx, 10000
        call Sleep
        call FreeConsole
        xor rcx, rcx
        call ExitProcess

.dll:

extern AllocConsole
extern SetConsoleTitleA
extern GetStdHandle
extern WriteConsoleA
extern Sleep

export newconsole
export strlen
export print

section .data BITS 64
console.writehandle:     dq 0
console.readhandle:              dq 0
console.write.result:    dq 0

section .text BITS 64
global strlen
strlen:
        push rax
        push rdx
        push rdi

        mov rdi, rcx
        xor rax, rax
        mov rcx, dword -1
        cld

        repnz scasb
        neg rcx
        sub rcx, 2

        pop rdi
        pop rdx
        pop rax
        ret

global print
print:
        mov rbp, rsp
        push rcx
        call strlen

        mov r8, rcx
        pop rdx
        mov rcx, [console.writehandle]
        mov r9, console.write.result
        push qword 0
        call WriteConsoleA
        ret

global newconsole
newconsole:
        push rax
        push rcx
        call AllocConsole
        pop rcx
        call SetConsoleTitleA
        mov rcx, -11
        call GetStdHandle
        mov [console.writehandle], rax
        pop rax
        ret
4

2 回答 2

3

我假设您正在谈论此功能:

global print
print:
        mov rbp, rsp
        push rcx
        call strlen

        mov r8, rcx
        pop rdx
        mov rcx, [console.writehandle]
        mov r9, console.write.result
        push qword 0
        call WriteConsoleA
        ret

x64 ABI 要求为寄存器中传递的参数保留堆栈空间。 WriteConsoleA可以随意使用这些堆栈位置 - 因此您需要确保已适当调整堆栈。就目前而言,您只推送最后一个保留的指针参数。我认为类似以下的内容会为您解决问题:

        push qword 0
        sub rsp, 4 * 8  // reserve stack for register parameters
        call WriteConsoleA
        mov rsp, rbp    // restore rsp
        ret

请参阅http://msdn.microsoft.com/en-us/library/ms235286.aspx(已添加重点):

x64 应用程序二进制接口 (ABI) 是一个 4 寄存器快速调用调用约定,这些寄存器具有堆栈支持

...

调用者负责为被调用者分配参数空间,并且必须始终为 4 个寄存器参数分配足够的空间,即使被调用者没有那么多参数。

于 2012-12-11T01:45:47.110 回答
2

根据调用约定,您必须清理放在堆栈上的参数。在这种情况下,适用于 的第 5 个参数WriteConsoleA。既然你有一份原件rsprbp里面,你可以rsp从重新加载rbp,或者只是在后面加8个call

于 2012-12-11T01:39:45.753 回答