假设我们有以下c ++代码:
int var1;
__asm {
mov var1, 2;
}
现在,我想知道的是,如果我不想在__asm指令之外定义var1,我需要做些什么才能把它放在里面。它甚至可能吗?
由于
答案 0 :(得分:12)
要做到这一点,你需要用_declspec(裸)创建一个“裸”方法,并自己编写通常由编译器创建的prolog和epilog。
序言的目的是:
一个结语必须:
这是一个标准的序言
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers
和标准的epilog:
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)
开始向上。
答案 1 :(得分: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
如果您不想在操作堆栈时更改局部变量的相对地址(即使用push
或pop
),则必须建立堆栈帧(即保存ebp
中堆栈的基础,并且相对于此值的地址位置),如cedrou's answer中所述。
答案 2 :(得分: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
}