2015-11-16 90 views
0

我有這樣的C代碼:ARM GCC的理解彙編函數調用

void initPIO_Port(AT91S_PIO *port) 
    { 
     port->PIO_PER=1<<PIN; 
     port->PIO_OER=1<<PIN; 
    } // initPIO_Port 

    int main(void) 
    {   
     initPIO_Port(PORT); 

      /* Loop for ever */ 
      while (1) { 
       ... 
      };  
    } 

翻譯的手臂,GCC到ARM彙編:

main: 
@ Function supports interworking. 
@ args = 0, pretend = 0, frame = 0 
@ frame_needed = 1, uses_anonymous_args = 0 
@int main(void) 
@{   
@ initPIO_Port(PORT); 
@ while (1) { 
.... 
@ };  
@} 

stmfd sp!, {fp, lr} 

add fp, sp, #4 

ldr r0, .L13 
bl initPIO_Port 

.L12:  
    ... 

b .L12 




initPIO_Port: 
@ Function supports interworking. 
@ args = 0, pretend = 0, frame = 8 
@ frame_needed = 1, uses_anonymous_args = 0 
@ link register save eliminated. 

@ void initPIO_Port(AT91S_PIO *port) 

str fp, [sp, #-4]! 
add fp, sp, #0 

sub sp, sp, #12 @ why subtract 12 - we're not using sp in following code ? 
str r0, [fp, #-8] @ first empty place is at fp-8? fp points to last full location on stack - is this right ? 
        @ why is input parameter in r0 saved on stack and then read in r3 ? 

    ldr r3, [fp, #-8] @  port->PIO_PER=1<<PIN; 
    mov r2, #2 
    str r2, [r3, #0] 

    ldr r3, [fp, #-8] @  port->PIO_OER=1<<PIN; 
    mov r2, #2 
    str r2, [r3, #16] 

add sp, fp, #0  @ previous value of sp 
ldmfd sp!, {fp} @ restore fp 
bx lr    @ return 

我已經FP和SP的問題理解的行爲註冊:

  • 爲什麼我從SP中減去12,然後不使用它?爲什麼12?

  • fp註冊的目的究竟是什麼?

  • 爲什麼r0寫入堆棧並讀取到r3?不都是爲了輸入參數嗎?

感謝您的幫助,

問候,

羅布。

+0

這是沒有優化? – andars

+0

未優化,它將爲傳入的參數和中間值騰出空間(並且可能根據abi對齊兩個字邊界)。 fp是幀指針,燒寫寄存器而不是使用sp來引用。並不少見,需要一些指令集。在這種情況下,它也可以節省sp的價值,所以你不必在後端進行數學運算,儘管在這種情況下也會更便宜。嘗試優化。 –

回答

1

這有點取決於代碼沒有(完全)優化,使它看起來相當混亂。

爲什麼我從sp中減去12然後不使用它?爲什麼12?

這是爲棧幀中分配空間,它認爲它需要12個字節的原因是,它會用一個詞來保存幀指針,用一個詞來存儲局部變量port和一個可能拯救返回地址(應該調用另一個函數)。

fp註冊的目的究竟是什麼?

這是幀指針。它使用它來訪問局部變量。它實際上大部分是多餘的,如果啓用優化,可能會被優化。

幀指針的一種用法是,如您所見,調用幀的幀指針存儲在幀指針的偏移量0處。這意味着您可以按照堆棧幀進行調試。

爲什麼r0寫入堆棧並讀取到r3?不都是爲了輸入參數嗎?

缺乏優化。 r0是第一個輸入參數,它存儲在變量的幀分配空間中,當變量被使用時,它將從幀中讀取。這樣做在重新使用r3時沒有問題,因爲編譯器會將在r3中傳遞的參數保存到該參數的幀分配空間中。

再一次,如果你已經打開優化,編譯器會意識到它不需要將變量port存儲在堆棧幀中,它會讓它生活在r0而不是。