私は MASM と Visual C++ を使用しており、x64 でコンパイルしています。これは私のC++コードです:
// include directive
#include "stdafx.h"
// external functions
extern "C" int Asm();
// main function
int main()
{
// call asm
Asm();
// get char, return success
_getch();
return EXIT_SUCCESS;
}
そして私のアセンブリコード:
extern Sleep : proc
; code segment
.code
; assembly procedure
Asm proc
; sleep for 1 second
mov ecx, 1000 ; ecx = sleep time
sub rsp, 8 ; 8 bytes of shadow space
call Sleep ; call sleep
add rsp, 8 ; get rid of shadow space
; return
ret
Asm endp
end
ret
ブレークポイントを使用して、アクセス違反が発生するコード行を特定しました。アセンブリ コードのステートメントの直後です。
追加情報:
私が読んだことから、 x64 は常に fastcall 規則を使用するため、fastcall規則を使用してパラメーターを渡しています( stdcall
Sleep
として宣言されていますが) 。関連するコードを削除
Asm
すると、プロシージャはエラーなしでコンパイルおよび実行されます。Sleep
stdcall規約で呼び出しを試みても
Sleep
、アクセス違反エラーが発生します。
明らかに、私の質問は、どうすればアクセス違反エラーを取り除くことができるかということです。何が間違っているのでしょうか?
編集:
Sleep(500);
これは、 C++ で生成されたアセンブリです。
mov ecx,1F4h
call qword ptr [__imp_Sleep (13F54B308h)]
この生成されたアセンブリは私を混乱させます...パラメーターをecxに移動するため、fastcallのように見えますが、同時にシャドウスペースを作成しません。そして、これが何を意味するのかわかりません:
qword ptr [__imp_Sleep (13F54B308h)]
.
もう一度、編集して、 の完全な分解を行いmain
ます。
int main()
{
000000013F991020 push rdi
000000013F991022 sub rsp,20h
000000013F991026 mov rdi,rsp
000000013F991029 mov ecx,8
000000013F99102E mov eax,0CCCCCCCCh
000000013F991033 rep stos dword ptr [rdi]
Sleep(500); // this here is the asm generated by the compiler!
000000013F991035 mov ecx,1F4h
000000013F99103A call qword ptr [__imp_Sleep (13F99B308h)]
// call asm
Asm();
000000013F991040 call @ILT+5(Asm) (13F99100Ah)
// get char, return success
_getch();
000000013F991045 call qword ptr [__imp__getch (13F99B540h)]
return EXIT_SUCCESS;
000000013F99104B xor eax,eax
}