2016-04-22 1 views
2

Question simple. La fonction asm en C est utilisée pour faire l'assemblage en ligne dans votre code. Mais qu'est-ce que ça rend? Est-ce le eax conventionnel, et si non, qu'est-ce qu'il retourne?Est-ce que __asm ​​{}; retourne la valeur de eax?

+3

Cela dépend du compilateur, mais autant que je sache, il n'est pas une fonction et il ne retourne rien, donc 'int i = __asm__() 'est juste une construction invalide – myaut

+3

Quel compilateur? Quel processeur? La plupart des processeurs n'ont pas de registre eax. – atturri

+1

True. D'accord en supposant que c'est un compilateur de studio visuel (pas sûr de savoir lequel) et un processeur Intel 32 bits. – Delupara

Répondre

3

__asm__ lui-même ne renvoie pas une valeur. C standard ne définit pas comment __asm__ doit gérer la valeur de retour, de sorte que le comportement peut être différent entre les compilateurs. Vous avez indiqué que l'exemple Visual Studio est valide, mais Visual Studio utilise __asm. __asm__ est utilisé au moins par GCC.

Visual Studio

Pour obtenir le résultat dans un programme C, vous devez placer la valeur de retour à eax dans le code assembleur, et le retour de la fonction. L'appelant recevra le contenu de eax comme valeur de retour.

Visual Studio 2015 documentation:

int power2(int num, int power) 
{ 
    __asm 
    { 
     mov eax, num ; Get first argument 
     mov ecx, power ; Get second argument 
     shl eax, cl  ; EAX = EAX * (2 to the power of CL) 
    } 
    // Return with result in EAX 
} 

GCC

GCC inline assembly HOWTO ne contient pas un exemple similaire. Cela signifie probablement que vous ne pouvez pas utiliser le retour implicite comme dans Visual Studio. Cependant, le HOWTO montre que vous pouvez stocker le résultat dans la variable C à l'intérieur du bloc d'assemblage et renvoyer la valeur de cette variable après la fin du bloc d'assemblage.

Un exemple d'une fonction de copie de chaîne, la valeur de retour de dest:

static inline char * strcpy(char * dest,const char *src) 
{ 
int d0, d1, d2; 
__asm__ __volatile__( "1:\tlodsb\n\t" 
         "stosb\n\t" 
         "testb %%al,%%al\n\t" 
         "jne 1b" 
        : "=&S" (d0), "=&D" (d1), "=&a" (d2) 
        : "0" (src),"1" (dest) 
        : "memory"); 
return dest; 
} 
2

C'est peu probable; par la spécification C99, sous le comportement de l'implémentation J3:

Le mot-clé asm peut être utilisé pour insérer le langage d'assemblage directement dans la sortie de traducteur (6,8). La mise en œuvre la plus courante est par une déclaration de la forme:

asm (character-string-literal);

Il est donc peu probable qu'un implémenteur va venir avec une approche à la fois insère la langue d'assemblage dans la sortie de traducteur et génère également un code de liaison intermédiaire supplémentaire pour câbler un registre particulier en tant que résultat de retour.

C'est un mot-clé, pas une fonction.

E.g. GCC utilise la sémantique de contrainte de type "=r" pour vous permettre d'avoir un accès en écriture à une variable dans votre assembly. Mais vous vous assurez que le résultat finit au bon endroit.