【问题标题】:How to call C++ functions in my assembly code如何在我的汇编代码中调用 C++ 函数
【发布时间】:2010-10-12 03:56:25
【问题描述】:

我需要从我的程序集中调用 PrintResult 来显示结果。我知道我必须在某处使用 extrn _PrintResult,我应该使用 call _PrintResult 调用该函数,但我不太确定如何使用它。任何建议

public _Square

.386

.model flat

.code

_Square proc

mov eax, [esp+4]

imul eax

ret

_Square endp

......这是我的 C++ 代码............

#include <iostream>

using namespace std;

enum ResultCode {ShowSquare};
enum SuccessCode {Failure, Success};

extern "C" long Square (long);

void main ()
 {
 long Num1; 
         long Num2;

 do
  {
  cout << "Enter Number to Square" << endl;
  cin >> Num1;
  Result = Square (Num1);
  cout << "Square is: " << Result << endl;
  } while (Result > 0);
 }

void PrintResult (ResultCode PrintCode, long Value) //PrintCode, long Value)
 {
 switch (PrintCode)
  {
  case ShowSquare:
    cout << "Display of square is: " << Value << endl;
    break;

  default:
    cout << "Error in assembly routines" << endl;
  }
}

【问题讨论】:

  • 你用的是什么汇编器和编译器?

标签: c++ assembly


【解决方案1】:

我通常不喜欢发布完整的代码,但试试这个:

32 位汇编

.386
.model flat
.code

_Square proc
mov eax, [esp+4]
imul eax

push eax ; Save the calculated result

; Call PrintResult here
push eax ; value
push 0 ; ShowSquare
call _PrintResult
add esp, 8 ; Clear the stack

pop eax ; Return the calculated result

ret
_Square endp

C++

#include <iostream>

using namespace std;

enum ResultCode {ShowSquare};
enum SuccessCode {Failure, Success};

extern "C" long Square(long);

int main(int argc, char* argv[])
{
    long Num1, Num2;

    do
    {
        cout << "Enter number to square" << endl;
        cin >> Num1;
        Num2 = Square(Num1);
        cout << "Square returned: " << Num2 << endl;
    }
    while (Num2);

    return 0; 
}

extern "C"
void PrintResult(ResultCode result, long value)
{
    switch (result)
    {
        case ShowSquare:
            cout << "Square is: " << value << endl;
            break;

        default:
            cout << "Error calculating square" << endl;
            break;
    }
}


因为你写的是C程序,所以默认的调用机制是cdecl,也就是说所有的参数都在栈上传递,返回值在eax中传回来,调用者负责清理之后的堆栈。

因此,为了调用 PrintResult,您必须在调用过程之前将所有参数压入堆栈。在程序返回后,我们必须清理我们的堆栈 (add esp, 8)。

由于cdecl调用约定允许在调用过程中修改eax,所以在PrintResult返回时eax可能不会被保留,所以我们在调用PrintResult之前保存计算结果,然后在调用返回后恢复。

我没有尝试过上面的代码,但我希望它能帮助你走上正轨。


注意:因为您使用的是 C++ 编译器,所以在 PrintResult 之前需要 extern "C"

【讨论】:

  • 为什么需要extern "C"
  • 因为它是一个 C++ 编译器,除非你把 extern "C" 放在那里,否则它会破坏方法名称,这意味着程序集中的调用必须使用破坏的名称。虽然技术上可行,但它不是很有趣! :P
  • @Miqueella,哇,非常感谢你,它成功了。我花了很多时间试图弄清楚。再次感谢
  • @justbrianr 这有意义吗?如果有什么不合理的地方,我很乐意再解释一下。另外,如果它对你有用,你会接受我的回答吗? ;)
  • 我想知道这是否会令人困惑......因为我们使用的是 cdecl 调用约定,eax 可能会在调用 PrintResult 期间被修改。我们不知道会不会,这取决于编译器今天的感受。我们不能抓住这个机会,所以我们在堆栈上存储了第二个副本,这样我们就可以在调用 PrintResult (pop eax) 后取回它。
猜你喜欢
  • 2016-09-07
  • 2017-02-18
  • 2016-08-27
  • 2013-03-13
  • 1970-01-01
  • 2012-04-21
  • 2014-11-30
  • 2011-09-04
  • 1970-01-01
相关资源
最近更新 更多