色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

透徹的理解機器代碼層面的函數調用

Linux閱碼場 ? 來源:未知 ? 作者:胡薇 ? 2018-05-25 14:40 ? 次閱讀

我是CPU阿甘, 上次我給大家承諾過,要講一講函數調用的秘密, 這個確實有點復雜, 想透徹的理解機器代碼層面的函數調用不容易。

我也是從無數的指令中悟出這個函數調用的秘密的, 所以慢慢來,不要急。 放松心情, 慢慢的品味,你可能需要多看幾遍才能明白。

但是你一旦理解了,絕對物超所值,因為你會了解到匯編寄存器,指針,以及他們在一起到底是怎么工作的。

首先, 一個程序一條一條的指令都的老老實實的放在內存的一個地方,這個地方是Linux老大分配的, 我干涉不了, 但是這些指令都是我打電話給硬盤, 讓他給運輸到內存的。然后Linux老大就會告訴我程序的入口點, 其實就是第一條指令的存放地址, 我就打電話問內存要這個指令, 取到指令以后就開始執行。這些指令當中無非有這么幾類:1. 把數據從內存加載我的寄存器里什么? 你不知道啥是寄存器? 寄存器就是我內部的一個臨時的數據存儲空間了2. 對寄存器的數據進行運算, 例如把兩個寄存器的數加起來3. 把我寄存器的數據再寫到內存里但是我一旦遇到像這樣的指令。"把寄存器ebp的值壓到棧里去“我就知道好戲要上場了, 函數調用就會開始。我們這些x86體系的機器有個特點,就是每個函數調用都會創建一個所謂的“幀”哈哈, 不要被這些術語嚇壞, 其實幀也就是我哥們內存中的一段連續的空間而已。像這樣:

現在這個指令來了:"把寄存器ebp的值壓到棧里去“"把esp的值賦給ebp"

"把esp 的值減去24”

“把10放到ebp 減去4的地址” (其實就是796嘛)“把20放到ebp減去8的地址” (其實就是792嘛)

" 把地址796作為數據放到 esp指向的地址“ (其實就是776嘛)" 把地址792作為數據放到 esp+4指向的地址" (其實就是780嘛)

這其實就相當于把 x 的指針 &x和 y 的指針 &y ,放到了特定的地方, 準備著要做什么事情 , 可能要調用函數了。

所以,所謂的指針就是地址而已。

我猜程序員寫的代碼應該是這樣:int x = 10;int y = 20;int sum= add(&x, &y);接下來的指令是這樣:“調用函數 add”我看到這樣的函數就需要特別小心, 因為我必須要找到 add函數返回以后的那條指令的地址, 把它也壓到棧里去。int x = 10;int y = 20;int sum = add(&x, &y);printf("the sum is %d\n",sum);假設這條指令的地址是100

注意啊, 把函數調用結束的以后的返回地址100壓入棧以后, esp 也發生變化了, 指向了772的位置我會找到函數Add 的指令,繼續執行"把寄存器ebp的值壓到棧里去“"把esp的值賦給ebp""把寄存器ebx的值壓入棧”你看每個函數的開始指令都是這樣, 我猜這應該是一種約定吧這里額外把ebx這個寄存器壓入棧, 是因為ebx可能被上個函數使用, 但是在add函數中也會用 , 為了不破壞之前的值, 只有先委屈一下暫時放到內存里吧。

“把ebp 加8的數據取出來放到 edx 寄存器” (ebp+8 不就是地址776嘛, 其中存放的是&x的地址, 這就是取參數了)“把ebp 加12的數據取出來放到 ecx 寄存器” (ebp+12 不就是地址780嘛, 其中存放的是&y的地址)注意啊, 現在edx的值是796, ecx的值是792 , 但他們仍然不是真正的數據, 而是指針(地址)!“把edx 指向的內存地址(796)的數據取出來,放到ebx 寄存器”“把ecx 指向的內存地址(792)的數據取出來,放到eax寄存器”此時此刻, 終于取到了真正的值, ebx = 10, eax = 20你暈了沒有? 如果你到此已經暈了, 建議你再讀一遍。 我想源代碼應該非常的簡單,就是這樣:int add(int *xp , int *yp){ int x = *xp; int y = *yp; ....}“把ebx 和 eax 的值加起來,放到 eax寄存器中”這個指令我最擅長做了。接下來的指令也很關鍵, add 函數已經調用完成, 準備返回了“把esp 指向的數據彈出的ebx寄存器”“把esp 指向的數據彈出到ebp寄存器”

"返回"我就會取出那個返回地址, 也就是 100, 去這里找指令接著執行其實就是這條語句:printf("the sum is %d\n",sum);問你一個問題, sum的值在那里保存著呢?對, 是在eax寄存器里 !搞定了,看著很復雜, 其實看透了也挺簡單吧。 函數調用,關鍵就是(1)把參數和返回地址準備好,(2)然后大家都遵循約定, 每次新函數都要建立新的函數幀: "把寄存器ebp的值壓到棧里去“ "把esp的值賦給ebp"(3) 函數調用完了, 重置 ebp 和esp ,讓他們重新指向調用著的棧幀。好了,今天就到此為止 , 把我也累壞了, 主人又要關機了,留一個問題吧:C語言編譯,鏈接以后直接就是機器碼, 那函數調用的操作都是上面講的。但是對于Python, Ruby 這樣的解釋型語言, 或者對于java 這樣的有虛擬機的語言, 他們的函數調用是什么樣的? 和上面講的有什么關系?

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5355

    瀏覽量

    120546
  • 匯編
    +關注

    關注

    2

    文章

    214

    瀏覽量

    25949
  • 函數調用
    +關注

    關注

    0

    文章

    19

    瀏覽量

    2599

原文標題:CPU阿甘:函數調用的秘密

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    C函數調用機制與棧幀原理詳解

    當一個C函數調用時,函數的參數如何傳遞、堆棧指針如何變化、棧幀是如何被建立以及如何被消除的,一直缺乏系統性的理解,因此決定花時間學習下函數
    發表于 06-08 10:49 ?1363次閱讀
    C<b class='flag-5'>函數</b><b class='flag-5'>調用</b>機制與棧幀原理詳解

    如何查看及更改函數/函數塊的調用環境

    模塊化設計的思想是把一些相似的功能(比如電機控制、閥控制)設計成函數函數塊,這樣就可以反復調用。其優點是:使程序架構更加清晰,避免重復編寫相似功能的代碼。不過可能會產生一個疑惑:既然
    的頭像 發表于 11-17 09:08 ?984次閱讀
    如何查看及更改<b class='flag-5'>函數</b>/<b class='flag-5'>函數</b>塊的<b class='flag-5'>調用</b>環境

    時鐘軟件層面和硬件層面的問題解釋

    前言說實話,我剛開始學的時候也沒咋的學明白,都是拿著別人的代碼抄一抄。那時我連軟件層面和硬件層面有時候都會搞混,所以我還是建議初學者多做筆記,多看看手冊。沒事也可以翻翻我的博客,如果在169芯片遇到
    發表于 11-29 07:08

    硬件層面的堆和棧基本介紹

    堆和棧!基本介紹在嵌入式和單片機開發領域中,堆和棧是非常重要的基礎知識,但對于許多開發者來說,對這方面的概念還是非常的模糊,甚至基本沒了解過。棧:基本上可以理解為,函數的局部變量都是存放...
    發表于 03-01 07:40

    CodeViz--一款分析C/C++源代碼函數調用關系的調用

    程序開發中,有時候需要閱讀別人的代碼,這時理解代碼的組織結構就顯得非常重要。CodeViz是一款分析C/C++函數調用關系的
    發表于 04-04 20:50 ?85次下載
    CodeViz--一款分析C/C++源<b class='flag-5'>代碼</b>中<b class='flag-5'>函數</b><b class='flag-5'>調用</b>關系的<b class='flag-5'>調用</b>

    如何在函數庫中調用指令?

    函數是一段可復用的代碼。我們通常把重復的代碼放進函數中并且在不同的地方去調用它。庫是函數的集合。
    的頭像 發表于 08-31 15:51 ?3831次閱讀

    關于DSP中fft函數調用方法

    以下主要是通過代碼調用ftf函數
    發表于 01-01 08:35 ?8268次閱讀

    C代碼與javaScript函數的相互調用問題應該如何解決

    本文檔的主要內容詳細介紹的是C代碼與javaScript函數的相互調用問題應該如何解決。
    發表于 03-05 11:47 ?17次下載

    系統調用與普通的函數調用之間的區別

    函數之間是可以相互調用的,這很簡單很happy有沒有。 要知道是代碼、是函數就可以相互調用,不管你用什么語言寫的。
    的頭像 發表于 02-15 11:47 ?3461次閱讀
    系統<b class='flag-5'>調用</b>與普通的<b class='flag-5'>函數</b><b class='flag-5'>調用</b>之間的區別

    嵌入式軟件架構設計之函數調用

    函數調用很好理解,即使剛學沒多久的朋友也知道函數調用是怎么實現的,即調用一個已經封裝好的
    的頭像 發表于 02-15 14:48 ?1120次閱讀
    嵌入式軟件架構設計之<b class='flag-5'>函數</b><b class='flag-5'>調用</b>

    函數調用時底層會發生什么

    如果你懂得用箱子打包東西,你就能明白函數調用是怎么一回事。 原來,在程序運行時每個被調用函數都有自己的一個箱子,假設這段代碼是這樣寫
    的頭像 發表于 02-17 14:47 ?666次閱讀
    <b class='flag-5'>函數</b><b class='flag-5'>調用</b>時底層會發生什么

    什么是函數調用

    函數調用,就是使用我們已經定義好的函數,或者C語言自帶的庫函數
    的頭像 發表于 04-04 17:21 ?5881次閱讀

    SCL中調用函數的示例

    在此,可插入函數 (FC) 調用函數塊 (FB) 調用函數塊可作為單實例、多重實例或參數實例進行調用
    的頭像 發表于 06-06 10:18 ?2238次閱讀

    python函數函數之間的調用

    函數函數之間的調用 3.1 第一種情況 程序代碼如下: def x ( f ): def y (): print ( 1 ) return y def f (): print ( 2
    的頭像 發表于 10-04 17:17 ?605次閱讀

    linux用gdb調試遇到函數調用怎么辦?

    linux用gdb調試遇到函數調用怎么辦? 在Linux上使用GDB調試時,遇到函數調用是一個常見的情況。函數
    的頭像 發表于 01-31 10:33 ?728次閱讀
    主站蜘蛛池模板: 成在线人免费视频| 国产亚洲AV精品无码麻豆| 精品国产午夜肉伦伦影院| 一本色道久久综合亚洲AV蜜桃| 久久久久亚洲精品影视| 中字幕久久久人妻熟女天美传媒| 欧美高清vivoesosexo10| 囯产精品久久久久久久久免费蜜桃| 我的家庭女教师| 久久精品视频在线看| yellow片高清视频免费看| 新香蕉少妇视频网站| 久久久精品久久久久三级| 超碰公开在线caopon| 亚洲色无码播放| 热久久综合这里只有精品电影| 国产偷国产偷亚州清高APP| 8050午夜二级一片| 亚洲1卡二卡3卡4卡新区在线| 麻1豆传媒2021精品| 国产成人永久免费视频| 最近日本MV字幕免费观看在线| 手机看片成人| 内射无码AV-区二区在线观看| 国产学生在线播放精品视频 | 浪荡受自我调教纯肉BL| 俄罗斯17vidio| 最近日本MV字幕免费观看在线| 色宅男午夜电影网站| 美女18毛片免费视频| 国产午夜精AV在线麻豆| 99热这里有精品| 一本之道高清在线观看一区| 日本一在线中文字幕| 久久精品AV无码亚洲色欲| 国产国拍亚洲精品永久软件| 10分钟免费观看视频| 亚洲精品国产高清嫩草影院| 日本老师xxxxx18| 免费女人光着全身网站| 黄色三级网站在线观看|