假设我们有以下 c++ 代码:
int var1;
__asm {
mov var1, 2;
}
现在,我想知道的是,如果我不想在 __asm 指令之外定义 var1,我需要做什么才能将其放入其中。甚至可能吗?
谢谢
假设我们有以下 c++ 代码:
int var1;
__asm {
mov var1, 2;
}
现在,我想知道的是,如果我不想在 __asm 指令之外定义 var1,我需要做什么才能将其放入其中。甚至可能吗?
谢谢
为此,您需要使用 _declspec(naked) 创建一个“裸”方法,并自己编写通常由编译器创建的序言和结语。
序言的目的是:
结语必须:
这是一个标准的序言
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)
并向上。
在汇编程序中创建 C 变量是不可能的:C 编译器必须知道变量(即它的类型和地址),这意味着它必须在 C 代码中声明。
可以做的是通过extern
C 中的声明访问在汇编程序中定义的符号。但这不适用于具有自动存储持续时间的变量,因为这些变量没有固定地址,而是相对于基指针引用。
如果您不想访问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
or pop
),则必须建立堆栈框架(即,将堆栈的基址保存在其中ebp
并相对于该值的地址局部变量)如cedrou 的回答中所述。
通过 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
}