Я использую 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
Заявление в моем коде сборки.
Дополнительная информация:
Я использую азЬсаИ Соглашение о передаче моих параметров в Sleep
(даже если он объявлен как STDCALL), так как из того, что я прочитал, x64 всегда будет использовать азЬсаИ условность.
мой Asm
процедура компилируется и выполняется без ошибок, когда я избавляюсь от Sleep
связанный код.
Даже когда я пытаюсь позвонить Sleep
с STDCALL Соглашение, я все еще получаю ошибку нарушения доступа.
Итак, очевидно, мой вопрос, как мне избавиться от ошибки нарушения доступа, что я делаю не так?
Редактировать:
Это сгенерированная сборка для Sleep(500);
в C ++:
mov ecx,1F4h
call qword ptr [__imp_Sleep (13F54B308h)]
Эта сгенерированная сборка сбивает меня с толку … она выглядит как fastcall, потому что она перемещает параметр в ecx, но в то же время не создает теневого пространства. И я понятия не имею, что это значит:
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
}
Если Asm()
были нормальной функцией C / C ++, например:
void Asm()
{
Sleep(1000);
}
Вот что генерирует мой x64 компилятор для него:
Asm proc
push rbp ; re-aligns the stack to a 16-byte boundary (CALL pushed 8 bytes for the caller's return address) as well as prepares for setting up a stack frame
sub rsp, 32 ; 32 bytes of shadow space
mov rbp, rsp ; finalizes the stack frame using the current stack pointer
; sleep for 1 second
mov ecx, 1000 ; ecx = sleep time
call Sleep ; call sleep
lea rsp, [rbp+32] ; get rid of shadow space
pop rbp ; clears the stack frame and sets the stack pointer back to the location of the caller's return address
ret ; return to caller
Asm endp
Вызывающая сторона отвечает за выделение места для параметров вызываемой стороне, и должен всегда выделять достаточно места для 4 параметров регистра, даже если вызываемый объект не имеет такого количества параметров.
Посмотрите на следующую страницу для получения дополнительной информации о том, как x64 использует стек:
Других решений пока нет …