Функцията за вградено асемблиране на C++ не работи правилно

Всеки път получавам различна върната стойност, така че правя нещо нередно. Ако заменя add с основен inc, той се връща правилно.

Ето кода.

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <iostream>

using namespace std;

int Add ( int _Number1, int _Number2 );

int main ( int _ArgumentCount, char * _Arguments[] )
{
    int nInput, nOutput;

    nOutput = Add ( 1, 1 );

    cout << "1 + 1 = " << nOutput << endl;
    cin >> nInput;

    return 0;
}

__declspec ( naked ) int Add ( int _Number1, int _Number2 )
{
    __asm   xor eax, eax
    __asm   mov eax, _Number1
    __asm   add eax, _Number2
    __asm   ret
}

Ето новия работещ код:

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <iostream>

using namespace std;

int Add ( int Number1, int Number2 );

int main ( int ArgumentCount, char * Arguments[] )
{
    int nInput, nOutput;

    nOutput = Add ( 1, 1 );

    cout << "1 + 1 = " << nOutput << endl;
    cin >> nInput;

    return 0;
}

int Add ( int Number1, int Number2 )
{
    __asm   mov eax, Number1
    __asm   add eax, Number2
}

person guitar-    schedule 21.08.2010    source източник
comment
Откъде знаеш, че _Number1 не е eax? Компилаторът има право да извиква функции с техните аргументи в регистрите. Мисля, че вашият проблем е, че не сте положили никакви усилия да избегнете стъпването на компилатора, като декларирате вашите използвани регистри и т.н. Погледнете разглобяването на вашата програма за доказателство.   -  person Borealid    schedule 21.08.2010
comment
Защо използвате __declspec(naked)? Сигурни ли сте, че трябва да направите това? Какво ще стане, ако не го направите?   -  person Greg Hewgill    schedule 21.08.2010
comment
@Borealid - Това е първият ми опит, не съм много сигурен какво правя. Мислех, че EAX е запазен за връщани стойности, кои регистри трябва да използвам? @Greg - Имах някои проблеми с компилацията без него. Търсих в Google и един човек във форума каза да използвам голата декларация.   -  person guitar-    schedule 21.08.2010


Отговори (1)


__declspec (naked) означава, че функцията е създадена без пролог или епилог код -- така че ако искате да получите достъп до формални параметри, трябва да напишете свой собствен пролог код, който да ви даде достъп до тях. Вашето xor също не постига нищо, тъй като незабавно презаписвате eax с друга стойност. Също така имайте предвид, че всеки идентификатор, започващ с долна черта, последвана от главна буква, е запазен, така че вашият код имаше недефинирано поведение. Опитайте да пренапишете функцията си като:

int Add ( int number1, int number2 )
{
    __asm   mov eax, number1
    __asm   add eax, number2
}

или пък напишете кода за достъп до параметрите на стека, без да зависи от пролог:

__declspec (naked) int Add2(int number1, int number2) { 
    _asm mov eax, [esp+4]
    _asm add eax, [esp+8]
    _asm ret
}

Не проверих, но предполагам, че оригиналният ви код се опитва да зареди параметрите от [ebp+8] и [ebp+12]. Това зависи от нормалния пролог код:

push ebp
mov ebp, esp

...което вашият __declspec (naked) специално е казал на компилатора да не генерира.

person Jerry Coffin    schedule 21.08.2010
comment
Благодаря много. Признавам, че когато не се компилира и намерих голото решение, дори не го прочетох. Много мързеливо от моя страна. За запазените имена също нямах представа. Благодаря много, вече работи. - person guitar-; 21.08.2010