Le code après conversion n'exécute pas une action donnée [dupliquer]
On m'a donné la tâche de convertir un certain code de C ++ à ASM basé sur la syntaxe AT&T, j'ai donc commencé avec des exemples simples et rencontré le premier problème.
code à partir duquel j'ai commencé l'exercice
void func() {
int num = 1;
std::cout << "before: " << num << std::endl;
num = num << 3;
std::cout << "after: " << num << std::endl;
}
ce qui donne un résultat:
before: 1
after: 8
ma variable de traduction num est la première variable locale, elle devrait donc être à l'adresse -4 (% ebp)
void func() {
int num = 1;
std::cout << "before: " << num << std::endl;
asm (
"mov -4(%ebp), %eax \n"
"sall $3, %eax \n"
"mov %eax, -4(%ebp) \n"
);
std::cout << "after: " << num << std::endl;
}
ce qui donne un résultat:
before: 1
after: 1
pourquoi ce code n'a aucun effet sur num var?
Réponses
Le code que vous écrivez est très spécifique à l'implémentation. Dans votre cas, le code ne fonctionne probablement pas car vous utilisez ebp
un registre d'adressage 32 bits, alors que vous exécutez sur une machine 64 bits, qui utilise rbp
.
CEPENDANT, vous abordez cela de manière incorrecte. Soit vous écrivez un assembly pur, soit vous utilisez l'assembly en ligne C (étendu) correct, qui s'interface correctement avec les variables locales. Sinon, le code se cassera dès que vous changerez quelque chose, comme vous l'avez vécu vous-même.
selon cette réponse, l'asm en ligne devrait ressembler à:
asm ( "assembly code"
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);
donc votre code pourrait ressembler à
asm (
"mov %0, %%eax;"
"sal $3, %%eax;"
"mov %%eax, %1;"
:"=r" (num)
:"r" (num)
:"%eax"
);
Cependant, vous n'avez pas besoin de spécifier et d'utiliser eax
, ainsi le code pourrait être simplifié (et clarifié) pour
asm (
"sal $3, %[num];"
:[num] "+r" (num)
);