【问题标题】:Inline Assembly GCD won't work内联汇编 GCD 不起作用
【发布时间】:2012-10-16 10:45:32
【问题描述】:

我一直在编写一个简单的 c++ 程序,它使用 Assembly 获取 2 个数字的 GCD 并将它们作为我观看的教程中使用的示例输出。我明白它在做什么,但我不明白为什么它不起作用。 编辑:应该添加,当它运行时,它根本不输出任何东西。

#include <iostream>
using namespace std;

int gcd(int a, int b)
{
int result;
_asm
{
    push ebp
    mov ebp, esp
    mov eax, a
    mov ebx, b
looptop:
    cmp eax, 0
    je goback
    cmp eax, ebx
    jge modulo
    xchg eax, ebx
modulo:
    idiv ebx
    mov eax, edx
    jmp looptop
goback:
    mov eax, ebx
    mov esp, ebp
    pop ebp

    mov result, edx
}

return result;
}

int main()
{
cout << gcd(46,90) << endl;
    return 0;
}

我在 32 位 Windows 系统上运行它,任何帮助将不胜感激。编译时出现 4 个错误:

warning C4731: 'gcd' : frame pointer register 'ebp' modified by inline assembly code
warning C4731: 'gcd' : frame pointer register 'ebp' modified by inline assembly code
warning C4731: 'main' : frame pointer register 'ebp' modified by inline assembly code
warning C4731: 'main' : frame pointer register 'ebp' modified by inline assembly code

【问题讨论】:

  • 这些不是错误,而是警告。但是除非你知道你在做什么,否则你不应该弄乱 ebp/esp - 删除处理这两个寄存器的行。 (从技术上讲,您可以将__declspec(naked) 添加到函数声明中,但不要这样做,这有点高级。)
  • 哦,好吧,但没有解释为什么它不运行。
  • 请注意,只有当除法将edx 变为0 或a 以0 开头时,您的代码才会到达goback(在这种情况下,您需要对edx 进行零初始化),这意味着它将始终返回 0。

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


【解决方案1】:

编译器会在函数的开头和结尾插入这些或等效的指令:

push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp

如果您手动添加它们,您将无法通过ebp 访问函数的参数,这就是编译器发出警告的原因。

删除这 4 条指令。

另外,开始使用调试器。今天。

【讨论】:

  • 试过了,现在它抛出了一个“gcdTest.exe 中 0x0040153b 处未处理的异常:0xC0000095:整数溢出。”错误。
  • 我的猜测是您的edx 在idiv 之前没有初始化,要初始化它,您需要使用cdq 指令将eax 签名扩展为edx。
  • 发生异常的指令是什么?那个地址 0x0040153b 是什么?调试器应该能够向您展示代码的反汇编。使用它。
猜你喜欢
  • 2020-08-24
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多