Etykiety w GCC inline assembly
W moich trwających eksperymentach z GCC inline assembly, napotkałem nowy problem dotyczący etykiet i wbudowanego kodu.
Rozważ następujący prosty skok:
__asm__
(
"jmp out;"
"out:;"
:
:
);
To nie robi nic poza skokiem do etykiety out
. Tak jak jest, ten kod kompiluje się dobrze. Ale jeśli umieścisz go wewnątrz funkcji, a następnie skompilujesz z flagami optymalizacji, kompilator narzeka: "błąd: symbol' out 'jest już zdefiniowany".
Wydaje się, że kompilator powtarza ten kod złożenia za każdym razem, gdy wchodzi w linię funkcji. Powoduje to powielenie etykiety out
, co prowadzi do powstania wielu etykiet out
.
W ten sposób możesz umieścić swój zespół do makr CPP i inline C funkcji, więc każdy może z niego korzystać w Dowolna funkcja/makro C. Funkcje Inline bardzo przypominają makra dużo, ale są czasami czystsze w użyciu. Strzeż się tego. we wszystkich tych przypadkach kod będzie powielane, więc tylko lokalne etykiety (z 1: style) powinny być zdefiniowane w tym kod asm.
Próbowałem znaleźć więcej informacji na temat tych "lokalnych etykiet" , ale nie mogę znaleźć niczego związanego z montażem w linii. Wygląda na to, że samouczek mówi, że lokalna etykieta to liczba, po której następuje dwukropek (jak 1:
), więc próbowałem użyć takiej etykiety. Co ciekawe, kod skompilowany, ale w czasie uruchomienia po prostu wywołał błąd segmentacji. Hmm...
2 answers
A deklaracja lokalnej etykiety jest liczbą, po której następuje dwukropek. Ale odniesienie do etykiety lokalnej wymaga przyrostka f
LUB b
, w zależności od tego, czy chcesz patrzeć do przodu, czy do tyłu - tzn. 1f
odnosi się do następnej etykiety 1:
w kierunku do przodu.
Więc deklarowanie etykiety jako {[3] } jest poprawne, ale aby się do niej odwołać, musisz powiedzieć jmp 1f
(ponieważ w tym przypadku skaczesz do przodu).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-10 00:24:19
Cóż, to pytanie nie staje się młodsze, ale są dwa inne ciekawe rozwiązania.
1) Ten przykład używa %=. %= w szablonie asemblera zastępuje się liczbą, która jest "unikalna dla każdego insn w całej kompilacji. Jest to przydatne do tworzenia lokalnych etykiet, do których odnosi się więcej niż jeden raz w danym insn."Zauważ, że aby użyć %=, musisz (najwyraźniej) mieć co najmniej jedno wejście (chociaż prawdopodobnie nie musisz go używać).
int a = 3;
asm (
"test %0\n\t"
"jnz to_here%=\n\t"
"jz to_there%=\n\t"
"to_here%=:\n\t"
"to_there%=:"
::"r" (a));
To wyjścia:
test %eax
jnz to_here14
jz to_there14
to_here14:
to_there14:
Alternatywnie, można użyć ASM goto (dodane w v4.5 myślę). W rzeczywistości pozwala to przeskoczyć do etykiet c zamiast tylko etykiet asm:
asm goto ("jmp %l0\n"
: /* no output */
: /* no input */
: /* no clobber */
: gofurther);
printf("Didn't jump\n");
// c label:
gofurther:
printf("Jumped\n");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-19 01:24:51