2016-05-05 5 views
2

J'essaie d'écrire un planificateur pour exécuter ce que nous appelons «fibres». Malheureusement, je ne suis pas vraiment habitué à l'écriture en ligne.assemblage en ligne - instructions de copie intermédiaires inutiles

typedef struct { 
    //fiber's stack 
    long rsp; 
    long rbp; 

    //next fiber in ready list 
    struct fiber *next; 

} fiber; 

//currently executing fiber 
fiber *fib; 

Ainsi, la première tâche est - évidemment - la création d'une fibre pour la fonction main de sorte qu'il peut être suspendu.

int main(int argc, char* argv[]){ 

    //create fiber for main function 
    fib = malloc(sizeof(*fib)); 
    __asm__(
     "movq %%rsp, %0;" 
     "movq %%rbp, %1;" 
     : "=r"(fib->rsp),"=r"(fib->rbp) 
     ); 

    //jump to actual main and execute 
    __asm__(...); 

} 

Ce sera compilé à

movl $24, %edi #, 
    call malloc # 
#APP 
# 27 "scheduler.c" 1 
    movq %rsp, %rcx;movq %rbp, %rdx; # tmp92, tmp93 
# 0 "" 2 
#NO_APP 
    movq %rax, fib(%rip) # tmp91, fib 
    movq %rcx, (%rax) # tmp92, MEM[(struct fiber *)_3].rsp 
    movq %rdx, 8(%rax) # tmp93, MEM[(struct fiber *)_3].rbp 

Pourquoi cette compilation mov s dans des registres temporaires? Puis-je me débarrasser d'eux?

La première version de cette question avait la sortie asm de gcc -O0, avec encore plus d'instructions et de temporaires.

Activer les optimisations ne les supprime pas.

+0

Avez-vous activé optimisations? – Jester

+0

@Jester Je n'avais pas au début, mais les allumer ne se débarrasse pas des temporaires (voir edit ci-dessus). – User1291

+0

C ne supporte pas _methods_ – Olaf

Répondre

3

les activer ne se débarrasse pas des

temporaires

Il ne se débarrasser de certaines charges supplémentaires et des magasins. Le fib est bien sûr toujours là en mémoire puisque vous l'avez déclaré comme variable globale. Le rax est la valeur de retour du malloc qui doit être affectée au fib en mémoire. Les deux autres lignes écrivent dans vos fib membres qui sont également requis.

Étant donné que vous avez spécifié des sorties de registre, le bloc asm ne peut pas écrire directement dans la mémoire. C'est facile à fixer avec une contrainte de mémoire si:

__asm__(
    "movq %%rsp, %0;" 
    "movq %%rbp, %1;" 
    : "=m"(fib->rsp),"=m"(fib->rbp) 
    ); 

Cela va générer:

call malloc 
    movq %rax, fib(%rip) 
    movq %rsp, (%rax) 
    movq %rbp, 8(%rax) 
+0

Vous devriez probablement utiliser '" = rm "' pour donner au compilateur l'option, cela n'aura pas d'importance dans ce cas, mais si vous écrivez du code qui regarde ces valeurs, le compilateur peut les garder dans regs inst ead de faire un magasin-> charger. (Bien qu'idéalement il y aurait un moyen de faire une variable C se référer à la valeur de 'rbp' sans utiliser d'instructions.) Clang fait parfois de mauvais choix si on lui donne des contraintes multi-options, donc vérifie le code pour ce cas. (En fait, je ne me souviens pas des détails quand j'ai vu que clang faisait mal avec les instructions GNU C 'asm', mais cela peut arriver.) –