简体   繁体   English

在C ++内联汇编中定义变量

[英]Defining a variable inside c++ inline assembly

Let's say we have the following c++ code: 假设我们有以下c ++代码:

int var1;

__asm {
    mov var1, 2;
}

Now, what I'd like to know is if I didn't want to define var1 outside the __asm directive, what would I have to do to put it inside it. 现在,我想知道的是,如果我不想在__asm指令之外定义var1,我该怎么做才能将其放入其中。 Is it even possible? 可能吗

Thanks 谢谢

To do that, you'll need to create a "naked" method with _declspec(naked) and to write yourself the prolog and the epilog that are normally created by the compiler. 为此,您需要使用_declspec(naked)创建一个“裸”方法,并编写自己通常由编译器创建的序言和结语。

The aim of a prolog is to: 序言的目的是:

  • set up EBP and ESP 设置EBP和ESP
  • reserve space on stack for local variables 在堆栈上为局部变量保留空间
  • save registers that should be modified in the body of the function 保存应在函数主体中修改的寄存器

An epilog has to: 结语必须:

  • restore the saved register values 恢复保存的寄存器值
  • clean up the reserved space for local variables 清理局部变量的保留空间

Here is a standard prolog 这是标准的序言

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

and a standard epilog: 和标准的结尾:

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

Your local variables will then begin at (ebp - 4) and go downward to (ebp - 4 - localbytes) . 然后,您的局部变量将从(ebp - 4)开始,然后向下至(ebp - 4 - localbytes) The function parameters will start at (ebp + 8) and go upward. 功能参数将从(ebp + 8)开始向上。

It' impossible to create a C variable in assembler: the C compiler has to know about the variable (ie its type and address), which means it has to be declared in the C code. 在汇编器中创建C变量是不可能的:C编译器必须知道该变量(即其类型和地址),这意味着必须在C代码中声明它。

What can be done is accessing symbols defined in assembler via extern declarations in C. That won't work for variables with automatic storage duration, though, as these don't have a fixed address but are referenced relative to the base pointer. 可以做的是通过C中的extern声明访问在汇编器中定义的符号。但是,这对于具有自动存储持续时间的变量不起作用,因为这些变量没有固定的地址,而是相对于基本指针引用的。

If you don't want to access the variables outside of the asm block, you can use the stack for storing assembler-local data. 如果您不想访问asm块之外的变量,则可以使用堆栈来存储本地汇编程序数据。 Just keep in mind that you have to restore the stack pointer to its previous value when leaving the asm block, eg 请记住,离开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

If you don't want the relative addresses of the local variables to change whenever you manipulate the stack (ie use push or pop ), you have to establish a stack frame (ie save the base of the stack in ebp and address locals relative to this value) as described in cedrou's answer . 如果您不想每次操作堆栈时都改变局部变量的相对地址(即使用pushpop ),则必须建立一个堆栈框架(即将堆栈的基数保存在ebp并相对于此值),如cedrou的答案中所述

Local variables are allocated and freed by manipulating the available space on the call stack via the ESP register, ie: 通过ESP寄存器在调用堆栈上操纵可用空间,可以分配和释放局部变量,即:

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

Generally, this is better handled by establishing a "stack frame" for the calling function instead, and then access local variables (and function parameters) using offsets within the frame, instead of using the ESP register directly, ie: 通常,最好通过为调用函数建立一个“堆栈框架”,然后使用该框架内的偏移量访问局部变量(和函数参数),而不是直接使用ESP寄存器来更好地解决此问题,即:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM