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.

Jak mam to obejść? Czy naprawdę nie można używać etykiet w montażu liniowym? Ten tutorial na GCC inline assembly wspomina, że:

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...

Więc wszelkie sugestie, podpowiedzi, odpowiedzi...?
Author: Channel72, 2010-10-10

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).

 45
Author: Matthew Slattery,
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");
 25
Author: David Wohlferd,
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