2010-01-22 13 views
32

Pamiętam, że widziałem sposób użycia rozszerzonego zespołu gcc do odczytu wartości rejestru i zapisania go w zmiennej C. Nie mogę, ale na całe życie pamiętam, jak sformułować oświadczenie asm. Każda pomoc jest doceniana.Odczytywanie wartości rejestru na zmienną C

+1

A skąd wiesz, co jest w EBX, gdy rozpoczyna się wykonywanie kodu C? – florin

Odpowiedz

0

Czy nie jest to this czego szukasz?

Składnia:

asm ("fsinx %1,%0" : "=f" (result) : "f" (angle)); 
+0

Zdajesz sobie sprawę, że zamierzasz odczytać jedną zmienną, obliczyć sinus, a następnie zapisać wynik w drugiej zmiennej. –

+0

@Samuel: To był tylko przykład składni. –

+0

Potrącony, ponieważ jest to przykład użycia rozszerzonego zestawu w GCC, a nie jak uzyskać wartość konkretnego rejestru w określonej zmiennej, czyli to, co zadał OP. Określając rejestry za pomocą "% 0" i "% 1", GCC wybierze odpowiedni rejestr w twoim imieniu. Nie ma pewności, że wybierze rejestr, na który masz nadzieję. –

5

nie wiem o gcc, ale w VS to jak:

int data = 0; 
__asm 
{ 
    mov ebx, 30 
    mov data, ebx 
} 
cout<<data; 

Zasadniczo, przeniosłem dane w ebx do zmiennej data.

+0

Tylko x86, tylko. Kompilatory Microsoft na x64 i Itanium nie obsługują wbudowanego zestawu. – ephemient

+0

Myślę, że montaż zostanie przetłumaczony na mov ebx, 30 mov dword ptr [dane], ebx – Sridarshan

+2

Dlaczego nie tylko 'mov danych, 30'? – Houssni

17

Oto sposób na ebx:

int main() 
{ 
    int i; 
    asm("\t movl %%ebx,%0" : "=r"(i)); 
    return i + 1; 
} 

Rezultat:

main: 
    subl $4, %esp 
    #APP 
      movl %ebx,%eax 
    #NO_APP 
    incl %eax 
    addl $4, %esp 
    ret 


Edit:

W "= R" (i) jest ograniczenie produkcji, informując kompilator, że pierwsze wyjście (% 0) jest rejestrem, który powinien zostać umieszczony w zmiennej "i". Na tym poziomie optymalizacji (-O5) zmienna nigdy nie jest zapisywana w pamięci, ale jest przechowywana w rejestrze eax, który również jest rejestrem wartości zwracanej.

+1

Chciałbym użyć ograniczenia '= rm' zamiast' = r'. Optymalizator kompilatora spróbuje wybrać najlepszą ścieżkę. Jeśli wbudowany asembler znajdował się w sytuacji, w której brak jest rejestru, '= r' może zmusić go do wygenerowania kodu mniejszego niż optymalny. '= rm' dałoby optymalizatorowi szansę użycia odwołania do pamięci, gdyby to był najlepszy wybór. W tym prostym przykładzie nie będzie to problemem, ale jeśli kod znajduje się w bardziej złożonej sytuacji, wówczas podanie opcji kompilatorowi może być korzystne. –

2

Spowoduje to przeniesienie rejestru wskaźnika stosu do zmiennej sp.

intptr_t sp; 
asm ("movl %%esp, %0" : "=r" (sp)); 

Wystarczy zastąpić „esp” z rzeczywistą zarejestrować jesteś zainteresowany (ale na pewno nie zrobić, aby stracić %%) i „SP” ze zmienną.

28

Idąc w innym kierunku niż inne odpowiedzi do tej pory, ponieważ nie jestem pewien, co chcesz.

GCC Manual § 5.40 Variables in Specified Registers

register int *foo asm ("a5"); 

Tutaj a5 to nazwa rejestru, które powinny być wykorzystane & hellip;

Oczywiście nazwa rejestru jest zależna od procesora, ale nie stanowi to problemu, ponieważ konkretne rejestry są najczęściej przydatne z wyraźnymi instrukcjami asemblera (patrz Extended Asm). Obie te rzeczy zazwyczaj wymagają warunkowania twojego programu zgodnie z typem procesora.

Definiowanie takiej zmiennej rejestru nie rezerwuje rejestru; pozostaje dostępny dla innych zastosowań w miejscach, w których kontrola przepływu określa, że ​​wartość zmiennej nie jest pod napięciem.

GCC Manual § 3.18 Options for Code Generation Conventions

-ffixed-reg

Treat rejestr o nazwie reg jako stały rejestru; wygenerowany kod nigdy nie powinien się do niego odwoływać (z wyjątkiem może jako wskaźnika stosu, wskaźnika ramki lub w innej ustalonej roli).

To może replikować odpowiedź Richarda w prostszy sposób,

int main() { 
    register int i asm("ebx"); 
    return i + 1; 
} 

choć jest to raczej bez znaczenia, ponieważ nie masz pojęcia, co jest w rejestrze ebx.

Jeśli połączeniu tych dwóch, przygotowanie tego z gcc -ffixed-ebx,

#include <stdio.h> 
register int counter asm("ebx"); 
void check(int n) { 
    if (!(n % 2 && n % 3 && n % 5)) counter++; 
} 
int main() { 
    int i; 
    counter = 0; 
    for (i = 1; i <= 100; i++) check(i); 
    printf("%d Hamming numbers between 1 and 100\n", counter); 
    return 0; 
} 

można zapewnić, że zmienna C zawsze używa rezyduje w rejestrze dla szybkiego dostępu, a także nie będzie się niszczona przez inny kod wygenerowany. (Handily, ebx jest wywoływany zapisywanie w zwykłych x86 zawijających konwencje, więc nawet jeśli zostanie niszczona przez wywołaniami innych funkcji opracowanych bez -ffixed-*, powinno się też przywrócony.)

Z drugiej strony, to na pewno nie jest przenośny i zazwyczaj nie jest to także wydajność, ponieważ ograniczasz wolność kompilatora.

Powiązane problemy