2009-09-08 96 views
5

比方说,我们有以下的C++代码:定义变量中的C++内联汇编

int var1; 

__asm { 
    mov var1, 2; 
} 

现在,想我所知道的是,如果我不想定义__asm指令外VAR1,我需要做些什么才能把它放进去。它甚至有可能吗?

由于

回答

12

要做到这一点,您需要使用_declspec(裸体)创建一个“裸”方法,并编写通常由编译器创建的序言和结语。

一个序言的目的是:

  • 设置EBP和ESP
  • 保留空间上堆叠为局部变量
  • 保存寄存器应在函数的主体被修改

的结语有:

  • 恢复保存的寄存器值
  • 清理局部变量

这里预留空间是一个标准的序言

push  ebp    ; Save ebp 
mov   ebp, esp   ; Set stack frame pointer 
sub   esp, localbytes ; Allocate space for locals 
push  <registers>  ; Save registers 

和一个标准的结尾处理:

pop   <registers> ; Restore registers 
mov   esp, ebp  ; Restore stack pointer 
pop   ebp   ; Restore ebp 
ret      ; Return from function 

你的局部变量将从(ebp - 4)开始,然后下降到(ebp - 4 - localbytes)。功能参数将从(ebp + 8)开始并向上。

3

它不可能创建汇编一个C变量:C编译器必须知道有关变量(即,其类型和地址),这意味着它具有在C代码中声明。

可以做的是通过C中的extern声明访问汇编程序中定义的符号。这对于具有自动存储持续时间的变量来说不起作用,尽管这些变量没有固定的地址,而是相对于基址指针。

如果您不想访问asm块之外的变量,则可以使用堆栈来存储汇编程序本地数据。请记住,你必须堆栈​​指针恢复到以前的值在离开asm块时,如

sub esp, 12  ; space for 3 asm-local 32bit vars 
mov [esp-8], 42 ; set value of local var 
[...] 
push 0xdeadbeaf ; use stack 
[...]    ; !!! 42 resides now in [esp-12] !!! 
add esp, 16  ; restore esp 

如果你不想局部变量的相对地址改变,只要你操作堆栈(即使用pushpop),则必须按照cedrou's answer中所述建立堆栈帧(即,将堆栈的基址保存在ebp中,并将地址相对于此值保存)。

+0

确定子ESP,3会给空间3 32位瓦尔?我的想法是,对于每个32位变量,我必须从esp中取4个变量。 – 2009-09-08 21:47:51

+0

至少C++在内部定义如下:var_4 = dword ptr -4 – 2009-09-08 21:48:27

+0

你是对的 - 不应该在深夜回答问题;) – Christoph 2009-09-08 22:53:44

3

局部变量分配和释放由通过ESP寄存器操作的调用堆栈上的可用空间,即:

__asm 
{ 
    add esp, 4 
    mov [esp], 2; 
    ... 
    sub esp, 4 
} 

一般来说,这是通过建立一个“堆栈帧”为调用函数更好地处理反而,然后访问使用偏移局部变量(和功能参数)的框架内,而是采用了ESP直接注册,即:

__asm 
{ 
    push ebp 
    mov ebp, esp 
    add esp, 4 
    ... 
    mov [ebp-4], 2; 
    ... 
    mov esp, ebp 
    pop ebp 
}