0

何かをポップせずにプッシュした、またはその逆だと思いましたが、何も問題が見つかりません! 適切にリンクする dll への呼び出しでコンソールに書き込みますが、不可解なことに無人地帯にいます... (アドレス 0x0000000000000000)

いくつかのスリープを入れましたが、API 呼び出し WriteConsoleA が返されていると確信しています。それは印刷機能の下の私の最後のretにあります。

何か案は?

。EXE:

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ます。rspにオリジナルのコピーがあるので、からrbpリロードするか、の後に8を追加することができます。rsprbpcall

于 2012-12-11T01:39:45.753 に答える