2013-12-12 51 views
1

我有用C++編寫的方法返回一個對象。這個方法是通過程序集調用的(一個非常長時間的原因)。例如:從程序集中調用C++方法返回對象數據

Person DoStuff(int a) 
{ 
    Person output; 

    output.Name = "Koder"; 
    output.Age = 1337; 
    output.Cash = 80.86; 

    cout << "Given number is " << a << endl; 

    return output; 
} 

我知道價值回報是討厭和壞,但這個問題不是這個問題。調用此方法如下所示:

Variant vMethod = &DoStuff; 
void* pMethod = vMethod.As<void*>(); 

int paramVal = 78; 

int* retVal = nullptr; 

__asm 
{ 
    push paramVal 
    call pMethod 
    mov retVal, EAX 
} 

當此方法的返回值爲int時,此功能完美無缺。但是現在返回一個對象,實際的call指令引發了一個異常。您可以猜到,例外是return聲明。我知道這會發生,當我這樣寫,但我不知道如何檢索非原始(或非整數,就此而言)返回值。谷歌搜索C++ /彙編函數調用沒有幫助很多。感謝任何能提供幫助的人。

+2

我對此沒有線索......我最好的猜測是:使用C++調用函數,然後不生成可執行文件,嘗試生成彙編代碼(gcc -S)並查看返回值被處理。 –

+0

幫助解散代碼。我能夠看到如何初始化要調用的方法的堆棧並返回要檢索的值。謝謝! –

回答

1

這取決於使用什麼樣的呼叫Calling Convention。它也取決於編譯器如何處理對象。在這種情況下,您的對象至少包含3個值,這使得所有值都不可能適合寄存器(您的代碼假設返回值將位於EAX中 - 如果您返回的是int,則返回值)。

從查看程序集看起來您使用的是x86 32位程序集。 在這種情況下,調用約定說你應該在堆棧上傳遞參數, 對於這種情況,我認爲x86位調用約定說你需要爲返回值自己保留內存並傳遞對象應該存儲的地址作爲參數。在Windows上,返回指針(用於存儲對象的地址)是第二個參數,在Linux上是第一個參數。

由於您未能做到這一點,DoStuff方法可能會覆蓋返回地址,並導致程序在返回指令上崩潰。

+0

這個,以及提供的評論,讓我弄清楚了。我需要爲輸出保留堆棧空間,並且將WORD中的對象反向(從右到左)推入堆棧。 –

相關問題