Вызов функции Sleep Win32 из сборки создает ошибку нарушения доступа

Я использую 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
}

1

Решение

Если 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

MSDN говорит:

Вызывающая сторона отвечает за выделение места для параметров вызываемой стороне, и должен всегда выделять достаточно места для 4 параметров регистра, даже если вызываемый объект не имеет такого количества параметров.

Посмотрите на следующую страницу для получения дополнительной информации о том, как x64 использует стек:

Распределение стека

5

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector