日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

报头中的偏移量作用_C语言中函数的实现

發(fā)布時間:2023/12/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 报头中的偏移量作用_C语言中函数的实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

符號表

C編譯器使用符號表來記錄程序中遇到的變量,類似匯編器中的label表,不過C編譯器中的符號表包括更多信息:名字、類型、已分配的內(nèi)存地址、變量申明域或作用域等

e.g 程序中有6個變量聲明,編譯器會生成6個表項的符號表,采用偏移量的方式記錄變量在內(nèi)存中的位置

編譯器的符號表

變量的空間分配

存放變量內(nèi)容的內(nèi)存有兩種區(qū)段:全局數(shù)據(jù)段(global data section)和運行時棧(run-time stack)。全局數(shù)據(jù)段是內(nèi)存中存放全局變量的區(qū)段,即所有靜態(tài)變量所在的地方;運行時棧則是局部變量所在的地方。

在LC-3體系計算機中,R4是一個專用寄存器,存放的是全局數(shù)據(jù)段的基地址,所以R4可以被看做成一個全局指針。

e.g 全局變量earth偏移量為4,將earth的內(nèi)容讀入寄存器R3,LC-3指令如下:LDR R3, R4, #4

局部變量就會存放在一個被稱作”活動記錄“(activation record)或者”堆棧幀“(stack frame)的內(nèi)存模板(memory template)中?;顒佑涗浘褪且欢芜B續(xù)的內(nèi)存,包含了當前函數(shù)中所有的局部變量。每個函數(shù)都有自己的活動記錄,當我們調(diào)用一個函數(shù)的時候,該函數(shù)活動記錄的最大地址存放在寄存器R5中,R5被稱為幀指針(frame pointer)。注意,在活動記錄中,變量的排放順序與他們在程序中的聲明順序是相反的。

e.g 變量amount在程序中是最先被聲明的變量,它也是距離幀指針R5最近的變量,訪問變量seconds,LC-3指令如下:LDR R0, R5, #-5

LC-3內(nèi)存中的一個活動記錄

當我們調(diào)用一個函數(shù)的時候,該函數(shù)的活動記錄被壓入當前棧,同時R5內(nèi)容被調(diào)整,指向當前棧頂,當該函數(shù)結束的時候,控制權被交還給調(diào)用者,活動記錄將被彈出當前棧,同時R5的內(nèi)容也將被修改,指向調(diào)用者活動記錄所在位置。整個過程中,寄存器R6始終指向運行時棧的頂部,R6為棧指針。

C語言中,函數(shù)調(diào)用包括三個步驟:

  • 調(diào)用:調(diào)用者將參數(shù)傳遞給被調(diào)用者,并交出控制權;
  • 執(zhí)行:被調(diào)用者執(zhí)行任務;
  • 被調(diào)用者返回函數(shù)結果,并將控制權交還給調(diào)用者;
  • 運行時棧

    在函數(shù)被調(diào)用時,我們需要激活被調(diào)用函數(shù),也就是說在函數(shù)被執(zhí)行前,必須要在內(nèi)存中,為該函數(shù)的局部變量分配空間。

    每個函數(shù)的活動記錄,在其每次被調(diào)用的時候,都會被系統(tǒng)在內(nèi)存中分配一個活動記錄空間。函數(shù)返回的時候,則將該活動記錄返還,以供其他函數(shù)調(diào)用使用,這樣是允許函數(shù)的遞歸操作的。其中采用數(shù)據(jù)結構”?!皝砀櫤瘮?shù)調(diào)用模式。

    e.g

    int main() { int a; int b;: b = Watt(a); b = Volta(a,b); }int Watt(int a) { int w;: w = Volta(w, 10); return w; }int Volta(int q; int r) { int k; int m;: return k; }

    上圖是棧在代碼運行的不同時刻的快照,每個陰影區(qū)代表一個特定函數(shù)的活動記錄,將數(shù)據(jù)項壓入棧時,棧頂總是向著低的內(nèi)存地址方向移動。其中R5總是指向當前活動記錄的某個地址(局部變量的起始地址),R6總是指向運行時棧頂。

    實現(xiàn)機制

  • 調(diào)用者將參數(shù)拷貝到被調(diào)用者所能訪問的內(nèi)存區(qū)域
  • 被調(diào)用函數(shù)的開始代碼,將活動記錄壓入棧,并在棧中保存一些備忘信息(保證控制權返回調(diào)用者后,調(diào)用者的原局部變量和寄存器內(nèi)容在調(diào)用前后沒有變化
  • 被調(diào)用者完成自己的工作
  • 被調(diào)用函數(shù)完成之后,將活動記錄出棧,并將控制權返回調(diào)用者
  • 調(diào)用者重獲控制權之后,讀取被調(diào)用者的返回值
  • e.g

    w = Volta(w, 10);

    1、調(diào)用

    通過將兩個參數(shù)值壓入運行時棧,向Volta傳遞參數(shù),R6指向運行時棧頂部,每當向棧中壓入一個數(shù)據(jù)項,首先遞減R6值,然后將數(shù)據(jù)存入R6指向的地址。在LC-3結構中,C函數(shù)的參數(shù),按照它們在函數(shù)調(diào)用的順序,從右到左依次被壓入棧。

    通過JSR指令,把控制權交給Volta

    AND R0, R0, #0 ADD R0, R0, #10 ADD R6, R6, #-1 STR R0, R6, #0 LDR R0, R5, #0 ADD R6, R6, #-1 STR R0, R6, #0 JSR Volta

    2、被調(diào)用函數(shù)的開始

    被調(diào)用函數(shù)的初始代碼,要完成與調(diào)用信息相關的備份操作:

    為返回值預留一個內(nèi)存位置,通過棧指針遞減,將一個內(nèi)存空間“壓”入棧,在被調(diào)用函數(shù)返回調(diào)用者之前,將返回值填入此內(nèi)存。

    調(diào)用者相關的信息的保存,即R7中調(diào)用者的返回地址和R5中調(diào)用者的幀指針(動態(tài)鏈)。

    被調(diào)用者調(diào)整R6的值,在??臻g中為它的局部變量分配足夠的空間,同時設置R5指向這些局部變量的基地址。

    Volta: ADD R6, R6, #-1 ADD R6, R6, #-1 STR R7, R6, #0 ADD R6, R6, #-1 STR R5, R6, #0 ADD R5, R6, #-1 ADD R6, R6, #-2

    3、被調(diào)用函數(shù)的結束

    如果存在返回值,則填寫活動記錄的返回值字段。

    將局部變量彈出棧

    恢復原動態(tài)鏈的內(nèi)容

    恢復返回地址

    通過RET指令,返回調(diào)用者

    LDR R0, R5, #0 STR R0, R5, #3 ADD R6, R5, #1 LDR R5, R6, #0 ADD R6, R6, #1 LDR R7, R6, #0 ADD R6, R6, #1 RET

    4、返回調(diào)用函數(shù)

    將返回值(如果有)出棧

    參數(shù)出棧

    JSR Volta LDR R0, R6, #0 STR R0, R5, #0 ; w = Volta(w, 10); ADD R6, R6, #1 ADD R6, R6, #2

    總結

    以上是生活随笔為你收集整理的报头中的偏移量作用_C语言中函数的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。