2012-09-19 14 views
7

Pracuję z zespołem ARM, gdzie muszę napisać jeden podprogram, dla którego podążam za konwencją wywołania ARM (to będzie musiało zostać zintegrowane z jakąś osobną implementacją wyższego poziomu gdzieś else) do przekazywania parametrów i zwracanych wartości. Teraz jest coś, czego ogólnie nie jestem pewien podczas pracy z zespołem.Przekazywanie parametrów i zwracanie wartości podprogramu w złożeniu

Tak więc od konwencji, jeśli dobrze rozumiem, argumenty są przekazywane w kolejności zaczynającej się od rejestrów r0 - r4, a następnie dla innych stosów argumentów są używane. Wartości zwracane są przekazywane do r0.

Oto, z czym jestem zdezorientowany. Jeśli mam zapisać kontekst r0 i wyskakuję po tym, nie ma możliwości zwrócenia wyniku, jedynym sposobem, w jaki można to zrobić, jest uszkodzenie pierwszego argumentu. Czy jest jakiś sposób obejścia tego problemu? Z góry dziękuję!

Odpowiedz

6

Po przekazaniu wartości zwracanej w r0, wywołujący oczekuje, że zrobi to. Wywołujący nie oczekuje, że r0 nadal będzie zawierał tę samą wartość, co pierwotny pierwszy parametr, ponieważ r0 jest konkretnie tam, gdzie jest zwracana wartość.

Zazwyczaj ARM calling convention requires that the subroutine preserves r4 through r11, a nie r0 do r3. Więc i tak nie ma sprzeczności.

+0

Domyślam się, że jest to obowiązkiem dzwoniącego, aby zapisać kontekst r0 przed wywołaniem funkcji. – as3rdaccount

+0

Z opublikowanego linku: * "r0 do r3: służy do przechowywania wartości argumentów przekazywanych do podprogramu, a także do przechowywania wyników zwróconych przez podprogram" *. – m0skit0

6

Dlaczego po prostu nie wypróbować tego samodzielnie i zobaczyć, co robi kompilator?

unsigned int fun (unsigned int a, unsigned int b) 
{ 
    return(a+b); 
} 

kompilacji do obiektu i demontażu

arm-none-eabi-gcc -O2 -c fun.c -o fun.o 
arm-none-eabi-objdump -D fun.o 

a wynik jest

00000000 <fun>: 
    0: e0810000 add r0, r1, r0 
    4: e12fff1e bx lr 

Menu a dwa wejścia i B są przekazywane w wykorzystaniem R0 R1. r0-r4 nie muszą być zachowywane, w szczególności r0, ponieważ nie można zachować wartości zwracanej. W związku z tym, że wymagany kod C, dwa operandy są dodawane razem, a ponieważ konwencja wywołania wymaga, aby wynik został zwrócony w r0. r0 = r0 + r1.

Kompilator musi być zgodny z konwencją, w przeciwnym razie kod, który generuje, nie będzie działał, więc można po prostu skompilować kod i rozmontować, aby dowiedzieć się całkiem sporo na temat konwencji wywoływania dla określonego kompilatora i celu.