【问题标题】:Changing Array Values In Function - Inline Assembly在函数中更改数组值 - 内联汇编
【发布时间】:2015-09-01 13:37:17
【问题描述】:

所以我不久前自学了 x86 汇编,只是在玩 C++ 中的内联汇编。

所以我想做的是在函数参数中,传入一个数组、一个索引( unsigned int )和一个数字。然后,通过汇编,它将数组的该内存位置中的值更改为传入的值。所以代码看起来像这样。

inline void Set( int pArray[], unsigned int pIndex, int pNum ) {
    __asm {
        mov ebx, pIndex
        mov eax, 4
        mul ebx
        mov ebx, pNum

        lea edi, pArray
        mov [ edi + eax ], ebx
    }
}

int main() {
    int myArray[ 5 ] = { 1, 2, 3, 4, 5 };
    Set( myArray, 2, 7 );
    std::cout << myArray[ 2 ] << std::endl;
}

所以代码应该加载数组地址的开头,获取索引并将其乘以 4,以便内存位置移动那么多字节,并将其更改为传入的值。但是,当我这样做时,值保持不变。这是为什么?出了什么问题?

【问题讨论】:

  • 您可能需要mov edi, pArray,否则您可能正在加载参数变量的地址,而不是它指向的位置。您可能也想使用调试器自学:)
  • 是的。这就是问题所在。我最初是从一个函数中写出来的,该数组可以在它的范围内访问,因此它可以工作,但是当封装在函数中时它停止工作,所以这很有意义,为什么我应该使用“mov”而不是“莉亚”。谢谢:-)

标签: c++ arrays assembly x86 inline-assembly


【解决方案1】:

lea 代表“加载有效地址”,您的 lea 放置参数的地址。你的意思是lea edi, [pArray]

但是,还有两件事: 1)你不必乘以四。你可以做lea edi, [pArray + 4*ebx] 由于“缩放索引字节”寻址模式允许您乘以 4 并添加一个立即地址。

2) 您假设 32 位。 2015 年中你用的哪台电脑还在 32 位模式下工作?

我对 intel 语法汇编感到生疏。我可以推荐你学习 GCC 中汇编程序和 C++ 代码的集成吗? https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

【讨论】:

  • 对于 1,lea edi, [ pArray + 4 * ebx ] 不会更改值。对于 2,这是一个很好的问题。我在 Visual Studio Professional 2010 中,它不允许我使用 64 位寄存器。我最初使用 64 位寄存器执行此操作,但一直收到错误 C2415。
  • 不需要加载有效地址,也不需要使用乘法指令。检查 gcc 编译器资源管理器显示的内容:goo.gl/njHPU3 只需像这样使用“缩放索引字节”寻址:mov [rdi + rsi * 4], edx 其中 rdi 是 linux 调用约定中的数组基地址,rsi 是索引参数,edx 是值
猜你喜欢
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多