2017-05-30 5 views
0

Je ne maîtrise pas le langage d'assemblage. J'essaye de faire un appel à une fonction, foo, qui prend dix arguments en virgule flottante. Après les huit premiers, en utilisant les registres xmm0-xmm7, je pousse les arguments sur la pile. J'obtiens des résultats presque corrects, sauf pour les deux dernières valeurs à virgule flottante, qui sont celles que j'ai mises sur la pile.Comment passer correctement les arguments flottants sur la pile à l'aide de la procédure d'appel ABI

Je suppose que mon erreur est avec comment j'appelle push, et l'alignement avec les valeurs. Je ne suis pas sûr cependant, et je n'ai pas pu trouver une solution. Je pense que ce serait une solution plutôt simple cependant.

Voici un morceau exemple de code de ce que je suis en train de réaliser:

#include <iostream> 

void* foo(float a_, float b_, float c_, float d_, float e_, float f_, float g_, float h_, float i_, float j_) 
{ 
    std::cout << "A=" << a_ << std::endl; 
    std::cout << "B=" << b_ << std::endl; 
    std::cout << "C=" << c_ << std::endl; 
    std::cout << "D=" << d_ << std::endl; 
    std::cout << "E=" << e_ << std::endl; 
    std::cout << "F=" << f_ << std::endl; 
    std::cout << "G=" << g_ << std::endl; 
    std::cout << "H=" << h_ << std::endl; 
    std::cout << "I=" << i_ << std::endl; 
    std::cout << "J=" << j_ << std::endl; 
    return NULL; 
} 

struct asm_call_data 
{ 
    void* (*_function)(...); 
    float _data[10]; 
}; 

int main() 
{ 
    asm_call_data call_data; 

    call_data._function = (void* (*)(...))&foo; 
    call_data._data[0] = 1.3; 
    call_data._data[1] = 2.4; 
    call_data._data[2] = 3.5; 
    call_data._data[3] = 4.7; 
    call_data._data[4] = 5.8; 
    call_data._data[5] = 6.9; 
    call_data._data[6] = 7.0; 
    call_data._data[7] = 8.1; 
    call_data._data[8] = 9.2; 
    call_data._data[9] = 10.3; 

    __asm__ __volatile__ (
     // create new stack frame 
     "pushq %%rbp;\r\n\t" 
     "movq %%rsp, %%rbp;\r\n\t" 
     // move call data _data values into xmm0, xmm1, xmm2 
     "movss 8(%%rax), %%xmm0;\r\n\t" 
     "movss 12(%%rax), %%xmm1;\r\n\t" 
     "movss 16(%%rax), %%xmm2;\r\n\t" 
     "movss 20(%%rax), %%xmm3;\r\n\t" 
     "movss 24(%%rax), %%xmm4;\r\n\t" 
     "movss 28(%%rax), %%xmm5;\r\n\t" 
     "movss 32(%%rax), %%xmm6;\r\n\t" 
     "movss 36(%%rax), %%xmm7;\r\n\t" 
     "push 40(%%rax);\r\n\t" 
     "push 44(%%rax);\r\n\t" 
     // align stack 
     "andq $-16, %%rsp;\r\n\t" 
     // make asm call 
     "call 0(%%rax);\r\n\t" 
     // restore stack frame 
     "movq %%rbp, %%rsp;\r\n\t" 
     "popq %%rbp;\r\n\t" 
    : 
    : "a"(&call_data) 
    : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" 
    ); 
} 

Voici les sorties que je reçois lors de la compilation et l'exécution. Je ne sais pas ce que l'avertissement me dit vraiment, et dans 'I =' j'ai un nombre très bas, mais le nombre suivant est correct.

[email protected]:~/Documents/Subproject$ g++ Main.cpp -o Main 
Main.cpp: Assembler messages: 
Main.cpp:78: Warning: indirect call without `*' 
[email protected]:~/Documents/Subproject$ ./Main 
A=1.3 
B=2.4 
C=3.5 
D=4.7 
E=5.8 
F=6.9 
G=7 
H=8.1 
I=4.51567e+27 
J=10.3 
[email protected]:~/Documents/Subproject$ 

Des idées sur la façon de résoudre ce problème? Est-ce que le reste de l'assemblage semble correct? Et, que me dit l'avertissement? Je n'ai pas une ligne 78 dans mon code ..

+1

Quel jeu d'instructions est-ce? Je suppose x86? –

+0

Hey, il fonctionne actuellement sur x64. –

+1

Doit signaler un échec majeur dans ce code. Il peut clobber la zone rouge. –

Répondre

1

Si vous faites l'alignement de la pile comme ça, vous devez le faire avant en poussant vos arguments.

Et, puisque C++ pousse des arguments de droite à gauche, vous devez pousser J (data[9]) avant I (data[8]).

+0

Existe-t-il un meilleur moyen d'aligner les piles? –