2006/12/05

C++ 底層實作

今天心血來潮(沒錯,高微暫時擱在一旁 XD),寫了個簡單的函式讓 g++ 編譯但不組譯。函式如下:

int f(int& r) {
  return r;
}

g++ 編譯的結果是:

 .file "test_r.cpp"
 .text
 .align 2
.globl __Z1fRi
 .def __Z1fRi; .scl 2; .type 32; .endef
__Z1fRi:
    pushl  %ebp
    movl   %esp, %ebp
    movl   8(%ebp), %eax
    movl   (%eax), %eax
    popl   %ebp
    ret

唔,馬上看到和 masm 不同的幾個地方(後來查到這是 AT&T syntax):register 的名字前面全部冠以 '%',push、mov 等指令後面全部多了 'l'(這代表操作為 32-bit),[ebp + 8] 變成 8(%ebp),最有趣的當然是雙引數指令的 destination 和 source 順序 ─ 剛好和 masm 相反 XD。也看到《Inside the C++ Object Model》所講的 function name mangling(__Z1fRi)。翻譯成 masm 並加上註釋:

__Z1fRi:                  ; C++ function name mangling
    ; next 2 lines build up the stack frame
    push  ebp
    mov   ebp, esp
    mov   eax, [ebp + 8]  ; copy the first parameter into eax
    mov   eax, [eax]      ; dereference eax and store the result in eax
                          ; eax is the return value
    ; clear stack frame
    ; arguments are cleared by the caller
    pop ebp
    ret

然後我讓 f 改而接收 int* 參數,編譯出來完全一樣(除了 mangled name),可見 reference 底層實作與 pointer 相同。在這個層次就可直觀看出,傳遞基本型別參數時,以 by value 方式傳遞會比 by reference 方式還快,因為前者少了 deference 的動作。

--
哇,高微!XD


又做一個實驗,看看 pass struct by value 時是否真的是 by value:

struct S {
  int a[5];
};

int f(S s) {
  return s.a[2];
}

g++ 給我的是:

__Z1f1S:
    pushl  %ebp
    movl   %esp, %ebp
    movl   16(%ebp), %eax
    popl   %ebp
    ret

顯然整個 array 就在 stack 上,確確實實是 pass by value。


繼續做實驗,看看 return struct by value 的狀況:

struct S {
  int i, j, k;
  S(int a, int b, int c): i(a), j(b), k(c) { }
};

S f() {
  return S(1, 2, 3);
}

g++ 開 O3 最佳化後的結果如下:

__Z1fv:
    pushl  %ebp
    movl   %esp, %ebp
    movl   8(%ebp), %eax    ; "first parameter" as a pointer
    movl   $1, (%eax)
    movl   $2, 4(%eax)
    movl   $3, 8(%eax)
    popl   %ebp
    ret    $4               ; "first parameter" cleared by the callee

當 S 內含一個 int 時,return value 放在 eax;當 S 內含兩個 int,return value 放在 eax 和 edx;當 S 內含三個 int(即上例),事情就生變了 ─《Inside the C++ Object Model》p.63 所講的手法活生生在眼前上演!g++ 將 S f() 改為 void f(S&),直接把初值填在第一參數所指向的空間!哇,太好玩了 XD!

--
好了,可以睡了 XD。

Blogger yen312/05/2006 6:04 pm 說:

debug 12人次達成

 
Blogger Celith12/06/2006 1:09 pm 說:

@@~
看不懂編譯訊息

 
Blogger Josh Ko12/06/2006 2:45 pm 說:

「讓 g++ 編譯但不組譯」所以結果是組合語言 XD。

 

<< 回到主頁