Kod po konwersji nie wykonuje danej czynności [duplikat]
Dostałem zadanie konwersji określonego kodu z C ++ na ASM w oparciu o składnię AT&T, więc zacząłem od prostych przykładów i napotkałem pierwszy problem.
kod, od którego zacząłem ćwiczenie
void func() {
int num = 1;
std::cout << "before: " << num << std::endl;
num = num << 3;
std::cout << "after: " << num << std::endl;
}
co daje wynik:
before: 1
after: 8
moja zmienna translacyjna num jest pierwszą zmienną lokalną, więc powinna znajdować się w adresie -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;
}
co daje wynik:
before: 1
after: 1
dlaczego ten kod nie ma wpływu na num var?
Odpowiedzi
Kod, który piszesz, jest bardzo specyficzny dla implementacji. W twoim przypadku kod prawdopodobnie nie działa, ponieważ używasz ebp
32-bitowego rejestru adresowego, podczas gdy pracujesz na komputerze 64-bitowym, który używa rbp
.
JEDNAK podchodzisz do tego nieprawidłowo. Albo piszesz czysty asembler, albo używasz poprawnego (rozszerzonego) zestawu wbudowanego C, który poprawnie łączy się ze zmiennymi lokalnymi. W przeciwnym razie kod zepsuje się, gdy tylko coś zmienisz, czego doświadczyłeś.
zgodnie z tą odpowiedzią asm inline powinien wyglądać następująco:
asm ( "assembly code"
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);
więc twój kod może wyglądać
asm (
"mov %0, %%eax;"
"sal $3, %%eax;"
"mov %%eax, %1;"
:"=r" (num)
:"r" (num)
:"%eax"
);
Jednak nie musisz określać i używać eax
, więc kod można uprościć (i wyjaśnić) do
asm (
"sal $3, %[num];"
:[num] "+r" (num)
);