• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Dict.CN 在線詞典, 英語學習, 在線翻譯

            學海苦作舟,書山勤為徑

            留下點回憶

            常用鏈接

            統計

            積分與排名

            Denoise

            English study

            Web技術

            數據壓縮

            一些連接

            最新評論

            Windows中C函數是什么?

             

            C語言中函數就是一些代碼的集合,實現相對單一的功能;應該有名稱、參數、返回值。實際上函數應該是能夠從調用程序中接受輸入,處理一定的邏輯,并最終能返回到調用程序的一段代碼的集合。

            本主要討論windowsC函數如何實現的;主要包括:函數調用約定、參數傳遞和返回。

            調用約定

            Windows中默認使用的cdecl調用約定,又叫C調用約定(不加任何修飾就是這種約定)。cdecl的調用約定意味著:

            1) 參數從右向左壓入堆棧

            2) 函數自身不清理堆棧;調用者負責清理,因此這種調用約定允許參數不固定

            3) 函數名自動加前導的下劃線

             

            例如:函數

            Void TestFun(int a,int b);

            等價于:

            Void __cdecl TestFun(int a,int b);

             

            如果有段代碼調用上面的函數,例如:

            TestFun(1,2);

            那么轉變為匯編的就是:

            Push 2

            Push 1

            Call TestFun

            Add esp 8          ;2個參數

             

            假設esp的指針在調用函數之前為20,那么上面代碼行對應的esp的值為:

            Push 2               ;esp =16

            Push 1               ;esp=12

            Call TestFun     ;esp=8

            Add esp 8          ;esp=20

            其中call指令會修改esp的值,即將函數的返回地址進棧。

             

            WINAPIstdcallcdecl不同之處TestFun自己修改堆棧;上面函數的匯編代碼是:

            Push 2

            Push 1

            Call TestFun

             

             

            參數傳遞

            C函數的參數傳遞都是通過堆棧來進行的。還是針對上面的函數來畫一下堆棧的內容:

             

            ßESP

            返回地址

            低地址

            1(參數a

             

            2(參數b

             

             

             

             

            高地址

            調用者將參數ab放到堆棧中;一旦進入函數體,函數需要讀取這些參數并進行處理。讀取函數的方式就是通過ESP的偏移來完成。

            Mov eax, [esp+4]     ;a的值

            Mov ebx,[esp+8]      ;b的值

             

            如果在進入函數取參數之前先要保存某些寄存器,例如:

            Push eax

            那么esp的基地址發生了變化就是esp+4,從而取ab的值就變成:

            Mov eax,[esp+8]          ;a的值

            Mov ebx,[esp+12]        ;b的值

             

            函數返回

            函數返回分為兩個部分:返回值的設置和返回調用者的位置。

            返回值

            一般函數的返回值都是通過eax這個寄存器傳遞給調用者的,因此如果函數有返回值都在eax中。但對于浮點數使用ST0而不是EAX寄存器。

             

            因此函數體中在RET之前,需要做的是:

            MOV EAX, XXX          ;XXX返回值

             

            在調用者中取返回值的做法就是:

            MOV [ret], EAX         ;ret存放返回值的變量

            如果返回值超過4個字節,高位放在EDX中。

             

            函數返回

            對于C約定的函數返回通過RET來完成。需要做的就是從堆棧中讀取返回地址,然后修改EIP寄存器的位置;ESP的值加4,即從堆棧中把返回值POP出來。

             

            對于STDCALL的約定,需要給RET傳遞一個參數,參數的內容為傳遞進來的參數占用堆棧的大小,目的是通過RET指令來修改ESP的棧頂位置;恢復到調用前的位置。

             

            不管上面約定,最后EIP指向調用者調用該函數的下一行指令。

            posted on 2008-10-18 00:07 笨笨 閱讀(1865) 評論(0)  編輯 收藏 引用 所屬分類: 編碼

            久久久久亚洲精品中文字幕| 亚洲婷婷国产精品电影人久久| 久久发布国产伦子伦精品| 狠狠色婷婷久久综合频道日韩| 久久综合给合久久国产免费| 亚洲天堂久久精品| 久久精品中文字幕一区| 国产精品免费福利久久| 欧美一级久久久久久久大片| 亚洲精品国产字幕久久不卡| 国产精品久久久久久久久久免费| 精品久久久久成人码免费动漫 | 伊人精品久久久久7777| 亚洲精品乱码久久久久久蜜桃图片| 国内精品久久久久久久久电影网| 97精品国产97久久久久久免费| 国产精品成人久久久久久久| 久久国产色AV免费观看| 中文字幕乱码人妻无码久久| 久久久久九九精品影院| 亚洲国产成人久久综合一 | 人妻无码久久一区二区三区免费| 久久99精品国产麻豆婷婷| 久久精品国产99久久无毒不卡| 一日本道伊人久久综合影| 欧美一区二区精品久久| 久久久久亚洲AV成人片| 99久久精品国产一区二区 | 一本色道久久88—综合亚洲精品 | 少妇被又大又粗又爽毛片久久黑人| 99久久婷婷免费国产综合精品| 色欲av伊人久久大香线蕉影院| 精品久久久久久久国产潘金莲 | 久久久久97国产精华液好用吗| 久久久久国产精品| 国产精品久久波多野结衣| 国产V综合V亚洲欧美久久| 成人综合伊人五月婷久久| 久久99免费视频| 品成人欧美大片久久国产欧美... 品成人欧美大片久久国产欧美 | 久久青青国产|