从程序集调用Win32的睡眠函数创建访问冲突错误 [英] Calling Win32's Sleep function from assembly creates access violation error

查看:269
本文介绍了从程序集调用Win32的睡眠函数创建访问冲突错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用MASM和Visual C ++,我在x64编译。这是我的C ++代码:

  // include指令
#includestdafx.h
/ / external functions
externCint Asm();
// main函数
int main()
{

//调用asm
Asm();
// get char,return success
_getch();
return EXIT_SUCCESS;
}

和我的汇编代码:

  extern Sleep:proc 
;代码段
.code
;装配过程
Asm proc
;睡眠1秒
mov ecx,1000; ecx =睡眠时间
sub rsp,8; 8字节的影子空间
call Sleep;调用sleep
add rsp,8;摆脱阴影空间
; return
ret
Asm endp
end

使用断点定位了发生访问冲突的代码行:紧跟在我的汇编代码中的 ret 语句之后。



额外资讯:




  • > fastcall 约定将我的参数传递到 Sleep (即使它被声明为 stdcall ),因为从我已经阅读,x64将总是使用 fastcall 约定。

    即使当我尝试调用 Sleep Sleep 相关代码。





很明显, ,我的问题是,如何摆脱访问冲突错误,我做错了什么?



编辑



这是C ++中 Sleep(500); 的生成程序集:

  mov ecx,1F4h 
call qword ptr [__imp_Sleep(13F54B308h)]

这个生成的程序集让我感到困惑...它看起来像fastcall,因为它将参数移动到ecx,但同时它不创建任何阴影空间。我不知道这是什么意思:
qword ptr [__imp_Sleep(13F54B308h)]



strong>再次,编辑

的完整反汇编

  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); //这里是由编译器生成的asm!
000000013F991035 mov ecx,1F4h
000000013F99103A call qword ptr [__imp_Sleep(13F99B308h)]
//调用asm
Asm();
000000013F991040 call @ ILT + 5(Asm)(13F99100Ah)
//获取char,返回成功
_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;将栈重新对齐到一个16字节的边界(CALL推送8字节为调用者的返回地址)以及准备建立一个栈帧
sub rsp,32; 32字节的影子空间
mov rbp,rsp;使用当前堆栈指针
完成堆栈帧;睡眠1秒
mov ecx,1000; ecx =睡眠时间
call Sleep; call sleep
lea rsp,[rbp + 32];摆脱阴影空间
pop rbp;清除堆栈帧并将堆栈指针设置回调用方返回地址的位置
ret;返回调用者
Asm endp

MSDN说


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

$ b有关x64如何使用堆栈的更多信息,请查看下面的页面:



a href =http://msdn.microsoft.com/en-us/library/ew5tede7.aspx =nofollow>堆栈分配


I'm using MASM and Visual C++, and I'm compiling in x64. This is my C++ code:

// 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;
}

and my assembly code:

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

Using breakpoints, I've pinpointed the line of code where the access violation occurs: right after the ret statement in my assembly code.

Extra info:

  • I'm using the fastcall convention to pass my parameters into Sleep (even though it is declared as stdcall), because from what I have read, x64 will always use the fastcall convention.

  • My Asm procedure compiles and executes with no errors when I get rid of the Sleep related code.

  • Even when I try to call Sleep with the stdcall convention, I still get an access violation error.

So obviously, my question is, how do I get rid of the access violation error, what am I doing wrong?

Edit:

This is the generated assembly for Sleep(500); in C++:

mov         ecx,1F4h  
call        qword ptr [__imp_Sleep (13F54B308h)]

This generated assembly is confusing me... it looks like fastcall because it moves the parameter into ecx, but at the same time it doesn't create any shadow space. And I have no clue what this means:
qword ptr [__imp_Sleep (13F54B308h)].

And again, edit, the full disassembly for 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  
}

解决方案

If Asm() were a normal C/C++ function, eg:

void Asm()
{
    Sleep(1000);
}

The following is what my x64 compiler generates for it:

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 says:

The caller is responsible for allocating space for parameters to the callee, and must always allocate sufficient space for the 4 register parameters, even if the callee doesn’t have that many parameters.

Have a look at the following page for more information about how x64 uses the stack:

Stack Allocation

这篇关于从程序集调用Win32的睡眠函数创建访问冲突错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆