注銷

          注銷

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            112 隨筆 :: 7 文章 :: 18 評論 :: 0 Trackbacks

          在傳統C中,函數的參數和返回值都是以復制傳送的.
          看這段代碼
          struct Big
          {
          ?char buf[1024];
          }B,B2;

          Big bigfun(Big b)
          {
          ?return b;
          }

          int main()
          {
          ?B2 = bigfun(B);
          ?return 0;
          }

          其中B2 = bigfun(B)要被由以下幾個過程組成
          1.B要以傳值方式傳送到函數的參數表中中
          2.如果返回值size很小,可以返回eax中
          ? 但是在這里,返回值size很大,要建立臨時變量
          ? 然后將臨時變量的地址入棧,此時非常象函數參數入棧
          ? 返回eax指向這個臨時變量
          3.將這個臨時變量拷貝到B2上

          B2 = bigfun(B);
          展開為
          ;構造臨時堆棧
          004017AE? sub???????? esp,400h?;堆棧大小1024(400h)
          ;由于函數調用是傳值方式,所以將B復制到bigfun中的參數中
          ;相當于將B push到堆棧中
          004017B4? mov???????? ecx,100h?;傳送大小1024(100h*4)
          004017B9? mov???????? esi,offset B (421138h) ;源是B首地址
          004017BE? mov???????? edi,esp?;目的為bigfun中的參數地址
          004017C0? rep movs??? dword ptr [edi],dword ptr [esi] ;復制
          ;調用函數,此時push eax中的eax并非是函數參數壓棧,而是將一個臨時對象的指針壓棧
          004017C2? lea???????? eax,[ebp-4C4h]
          004017C8? push??????? eax?;將堆棧中一個臨時對象地址壓堆棧
          004017C9? call??????? bigfun (401750h) ;調用函數
          004017CE? add???????? esp,404h?;清除堆棧(400h+4),堆棧跳過函數參數表和函數返回地址
          ;臨時對象為返回變量,eax指向這個地址
          ;將這個臨時對象復制另一個臨時對象上
          004017D4? mov???????? ecx,100h?;傳送大小1024(100h*4)
          004017D9? mov???????? esi,eax?;目的上面臨時對象的地址
          004017DB? lea???????? edi,[ebp-8CCh] ;堆棧中第三個臨時對象
          004017E1? rep movs??? dword ptr [edi],dword ptr [esi] ;復制
          ;將第二個臨時對象復制到B2上
          004017E3? mov???????? ecx,100h?;傳送大小1024(100h*4)
          004017E8? lea???????? esi,[ebp-8CCh] ;堆棧中第三個臨時對象
          004017EE? mov???????? edi,offset B2 (421538h) ;目的為首地址
          004017F3? rep movs??? dword ptr [edi],dword ptr [esi] ;傳送


          Big bigfun(Big b) {
          展開為
          ;初始化堆棧,以ebp為基準,ebp+4指向為return address
          ;ebp+8為剛才壓入堆棧的上層函數中的臨時對象的地址
          ;ebp-4為臨時堆棧中第一個局部變量
          00401750? push??????? ebp?
          00401751? mov???????? ebp,esp?;ebp此時指向以前保存bp
          00401753? sub???????? esp,0C0h?;建立臨時堆棧,大小0C0h
          00401759? push??????? ebx?
          0040175A? push??????? esi?
          0040175B? push??????? edi
          ;初始化堆棧全部為0xcc
          0040175C? lea???????? edi,[ebp-0C0h]
          00401762? mov???????? ecx,30h
          00401767? mov???????? eax,0CCCCCCCCh
          0040176C? rep stos??? dword ptr [edi]
          ?return b;
          ;復制b到那個臨時對象上
          0040176E? mov???????? ecx,100h
          00401773? lea???????? esi,[b]
          00401776? mov???????? edi,dword ptr [ebp+8] ;ebp+8為參數表中的參數地址
          00401779? rep movs??? dword ptr [edi],dword ptr [esi]
          ;返回那個臨時變量的地址
          0040177B? mov???????? eax,dword ptr [ebp+8]
          }

          posted on 2006-11-19 10:13 注銷..... 閱讀(255) 評論(0)  編輯  收藏 所屬分類: c++
          主站蜘蛛池模板: 彭阳县| 大城县| 焦作市| 乐亭县| 嘉黎县| 松阳县| 锦屏县| 明溪县| 昌乐县| 金川县| 托克逊县| 衡水市| 霍城县| 读书| 宕昌县| 贵阳市| 安远县| 徐水县| 布尔津县| 社旗县| 大名县| 濮阳县| 合作市| 桐城市| 彰武县| 桂平市| 营口市| 安徽省| 西平县| 阳西县| 天津市| 连平县| 柳州市| 黄陵县| 株洲市| 蓬溪县| 永兴县| 丰顺县| 桓台县| 广丰县| 延边|