【问题标题】:Defining a variable inside c++ inline assembly在 C++ 内联汇编中定义一个变量
【发布时间】:2010-11-26 15:29:19
【问题描述】:

假设我们有以下 c++ 代码:

int var1;

__asm {
    mov var1, 2;
}

现在,我想知道的是,如果我不想在 __asm 指令之外定义 var1,我该怎么做才能将其放入其中。有可能吗?

谢谢

【问题讨论】:

  • 只是添加authoritative source虽然__asm 块可以引用C 或C++ 数据类型和对象,但它不能使用MASM 指令或运算符定义数据对象。具体来说,您不能使用定义指令 DB、DW、DD、DQ、DT 和 DF,或运算符 DUP 或 THIS。 将 cedrou 的答案作为解决方案。

标签: c++ c assembly visual-c++ inline-assembly


【解决方案1】:

不可能在汇编程序中创建 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),则必须建立堆栈帧(即保存堆栈的基数)在ebp 和地址本地人相对于这个值)如cedrou's answer 中所述。

【讨论】:

    【解决方案2】:

    为此,您需要使用 _declspec(naked) 创建一个“裸”方法,并自己编写通常由编译器创建的序言和结语。

    序言的目的是:

    • 设置 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】:

      通过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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-07
        • 1970-01-01
        • 1970-01-01
        • 2018-09-15
        • 1970-01-01
        • 2019-12-31
        • 1970-01-01
        • 2017-01-30
        相关资源
        最近更新 更多