2011-06-22 550 views
0

任何人都可以告訴我x86 ASM中的以下代碼是幹什麼的?它只是一個大文件的一部分,但這只是讓我失望。x86彙編代碼

find_max: 
    6 .LFB0: 
    7   .cfi_startproc 
    8   pushq %rbp 
    9   .cfi_def_cfa_offset 16 
10   movq %rsp, %rbp 
11   .cfi_offset 6, -16 
12   .cfi_def_cfa_register 6 
13   movl %edi, -20(%rbp) 
14   movl -20(%rbp), %eax 
15   cltq 
16   movl a(,%rax,4), %eax 
17   movl %eax, -4(%rbp) 
18   movl -20(%rbp), %eax 
19   movl %eax, -8(%rbp) 

具體來說,

  • 什麼最初%EDI在第13行?
  • 爲什麼代碼引用-20(%rbp)?
  • 第16行到底是做什麼的?
  • 在32位寄存器和64位寄存器之後進行切換(例如第15行),背後的智慧是什麼?

C代碼我拆開來得到這個去像下面這樣:

extern int a[]; 

int find_max(int n) 
{ 
    int max = a[n]; 
    int pos = n; 
    int x; 

    while (n > 0) 
    { 
     n--; 
     x = a[n]; 

     if (x > max) 
     { 
      max = x; 
      pos = n; 
     } 
    } 
    return pos; 
} 
+0

如果你有C代碼,你不知道它在做什麼?你究竟想問什麼? –

回答

7

什麼是最初在%edi 13行?

rdi是AMD/Linux 64位ABI的第一個參數傳遞寄存器。 edi正在此代碼中使用,因爲您的函數需要32位int參數。


爲什麼代碼引用-20(%rbp)

它將傳入的參數保存到堆棧;大概你正在編譯低優化或沒有優化,所以每個變量都得到一個真正的內存地址。如果開啓優化,您可能會看到這些操作消失。


而究竟是什麼線16嗎?

線16是一個數組索引操作:

movl a(,%rax,4), %eax 

的AT & T語法用於存儲器尋址是有些奇怪尋找。它打破瞭如:

段覆蓋:簽訂偏移(基準,指數,規模)

在你的情況下,數組的地址被用作偏移字段,你有沒有基地寄存器或段覆蓋,標度爲4,正在使用的變址寄存器爲rax。這打破了喜歡的東西沿着這類似於C的僞代碼的行:

eax = *(int *)((char *)a + (rax * 4)) 

背後有什麼在32位寄存器和64位寄存器後面的開關(例如智慧第15行的情況)?

我沒有看到第15行這樣的事情,但它做的原因是因爲你的函數使用了大量的int - 因爲int是32位的,編譯器使用32位的寄存器。無關緊要或編譯器正在使用臨時寄存器,它將選擇本機64位大小。

+0

最後一行更像'eax = *((int *)((char *)a + rax * 4));'。代碼考慮了int的大小。 – cHao

+0

@ cHao,是的,這是一個更明顯的描述。我在示例中壓縮了一些冗餘,以使其與原始代碼的某些外表匹配。我會更新它。 –

+0

非常感謝。這清理了很多東西。 :) @cHao,也謝謝你:) – arkati