2011-01-09 9 views
5

Czy istnieje sposób zmuszenia gcc do przekazania parametrów funkcji na stosie?Wymuś podanie gcc parametrów na stosie

Nie chcę używać rejestrów do przekazywania parametrów.

Aktualizacja: I'am stosując ramię gcc z CodeSourcery

+3

Dlaczego przekazywanie parametrów w rejestrach jest złe? –

+0

To nie jest złe. Po prostu chcę, aby parametry były przekazywane w ten sposób, ponieważ // emuluję // procedurę tworzenia wątku (i alokacji stosu). – cojocar

+0

Jaka architektura/ABI? – ephemient

Odpowiedz

0

Według: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf

pierwszych czterech rejestrów R0-R3 (A1-A4) są wykorzystywane do przekazywania wartości argumentu do podprogramu i zwrócenie wyniku z wartości funkcji . Mogą one również być używane do utrzymywania wartości pośrednich w ramach procedury (ale ogólnie, tylko pomiędzy wywołaniami podprogramów).

Istnieją, na ARM, inne konwencje wywoływania, ale domyślne, które znam. A oto dlaczego:

  1. Dlaczego chcesz? Twoja funkcja nie byłaby wywoływana w postaci skompilowanej przez inne funkcje, co powodowałoby bałagan zgodności.
  2. Twoje połączenia z funkcjami systemowymi zgodnymi z ABI nie zadziałają, chyba że kompilator byłby w stanie rozróżnić konwencje wywoływania. Teraz wiem, że w przeszłości istnieją różne konwencje wywoływania dla x86-32, ale zauważ, że x64 jest prostszy (AMD64 kontra Microsoft). Dlaczego, podczas projektowania ARM calling convention, pozwoliłbyś na tak wiele różnych konwencji telefonicznych? Tworzy bałagan zgodności.
+1

Tak, masz rację. To jest dziwne, zwłaszcza z powodów, o których wspomniałeś. Chodzi o to, że zdefiniowana funkcja była głównym elementem wątku - w niestandardowym środowisku (OS). Niestandardowy system operacyjny przesunie argument wątku na stosie. Aby respektować ABI, istnieją dwa sposoby obejścia: wstaw argument do r0 lub zadeklaruj * thread_func (uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3, void * param) *. Dzięki! – cojocar

+1

Dlaczego nie umieścić ich w rejestrach? Będziesz musiał zachować rejestry przez wątki, ale musisz mimo wszystko - wyobraź sobie, że podczas wykonywania wątków zmienisz wątki, a wartości rejestru starej funkcji pozostały na miejscu ... gdyby to zrobił system operacyjny, byłby bardzo brudny. –

+0

Wątek jest tworzony z przestrzeni użytkownika i nie ma API (syscall) do ustawiania wartości rejestru dla nowo utworzonego wątku. – cojocar

1

Możesz spróbować owijać parametry w strukturze; Na przykład, jeśli funkcja jest int calc_my_sum(int x, int y) {return x+y;} można zmienić w następujący sposób (brzydki):

struct my_x_y { 
    int x, y; 
    my_x_y(): x(0), y(0) {} // a non-trivial constructor to make the type non-POD 
}; 

int calc_my_sum(my_x_y x_and_y) { 
    // passing non-POD object by value forces to use the stack 
    return x_and_y.x + x_and_y.y; 
} 

Alternatywnie, można po prostu dodać 4 parametry obojętne na wykorzystanie rejestrów, więc inne parametry będą używać stosu:

struct force_stack_usage { 
    int dummy0, dummy1, dummy2, dummy3; 
} 

int calc_my_sum(force_stack_usage, int x, int y) { 
    return x + y; 
} 
+0

Fajny hack! Pierwsze rozwiązanie to tylko C++, zapomniałem wspomnieć, że potrzebowałem rozwiązania C. Dzięki. – cojocar

+1

Nie ma potrzeby, aby dziwaczny konstruktor C++ osiągał to, co chcesz. W C struktury są po prostu kopiowane na stosie. W C99 można nawet wywołać funkcję z 'calc_my_sum ((my_x_y) {.x = 5, .y = 7}) lub owinąć taką rzecz w makro bez problemów. –

0

Miejsce zapisania zmiennej lokalnej zależy od sposobu jej użycia. Jeśli chcesz uzyskać adres zmiennej lokalnej, zmienna lokalna może być przechowywana tylko na stosie. Kiedy więc przekażesz podprocedurze wskaźnik, ten parametr zostanie przekazany przez stos.

+0

Nie jestem pewien, czy to jest odpowiedź na pytanie, czy nie ... – Nanomurf

Powiązane problemy