程式的連結與裝入(動、靜態重定位)
原由:
多道程式環境下,程式是併發執行的,所以要使程式執行,必須先為之建立程序,而建立程序的第一件事就是將程式和資料裝入記憶體
目的:
使用者程式到記憶體可執行程式的步驟:
即
下面開始將程式“連結”和“裝入”的具體情況:
程式的連結:
源程式經過編譯後,得到一組目標模組,再利用“連結程式”將這組目標模組連結起來,形成一個完整的裝入模組(即可執行檔案)
如下圖:源程式編譯後得到三個目標模組A、B、C,長度分別為L、M、N,連結後形成右側的裝入模組:
連結時需要做兩個工作:
Ø 相對地址進行修改(變化以後還是相對地址),地址都變為相對最上層模組的起始地址來計算。
Ø 變化外部呼叫符號,如CALL B------> JSR“L”
CALL B為呼叫B模組,JSR“L”為跳轉到L行
連結前A和B為兩個不同的模組,在A模組中想執行B模組,要使用呼叫(CALL)語句;連結後A和B為同一模組,若想達到同樣地效果,只需在本模組中使用跳轉語句(JSR)跳轉到想執行的地方即可。
程式的裝入:
即將連結好的模組裝入記憶體
邏輯地址與實體地址
使用者程式編譯為目標模組後,會對每個模組內部(程式資料等)進行編址,此時編好的地址叫做邏輯地址或相對地址(下面的絕對裝入方式除外),都是相對於本模組的起始地址(一般從0開始)計算的。進行連結後某些模組的相對地址會發生變化,地址都變為相對於裝入模組
通常將記憶體的實際地址稱為實體地址
分類
Ø 絕對裝入方式
Ø 可重定位裝入方式(靜態重定位)
Ø 動態執行時裝入方式(動態重定位)
解析
(1)絕對裝入方式
程式編譯時,如果知道程式將駐留在記憶體的什麼位置(起始地址),那麼編譯生成的目的碼,將採用絕地地址進行編址,即起始地址不從0開始,從上面所知的記憶體起始地址開始編址。
例如:事先已知使用者程式(程序)駐留在從1000號單元處開始的位置,則編譯程式所產生的目標模組(即裝入模組)便從1000處開始向上擴充套件:
由於採用的是絕對地址,所以將裝入模組直接裝入記憶體即可,無需進行地址變換。
(2)可重定位裝入方式(靜態重定位)
Ø 出現:
編譯時將程式裝入指定的記憶體空間,必須需要程式設計師熟悉記憶體的使用情況
絕對裝入方式只能將目標模組裝入到記憶體中事先指定的位置。而在多道程式環境下,編譯程式不可能預知所編譯的目標模組應放在記憶體的何處
可重定位方式可根據記憶體的當前情況,將裝入模組裝入到記憶體的適當位置
Ø 原理:
源程式編譯生成的目標模組都採用相對地址進行編址,即每個模組都從0開始編址,當然連結後的模組也採用相對地址編址
將裝入模組裝入記憶體後,模組中的程式和資料等,在記憶體中都將具有一個實體地址,此實體地址是相對於記憶體的起始地址進行編址的,所以與原先模組中的邏輯地址(相對於模組的起始地址進行編址)不同,所以為了得到實體地址需要對邏輯地址進行改變。而此地址變化的過程就叫做重定位,又因為地址變換通常是在裝入時一次完成的,以後不再改變,故稱為靜態重定位。如下圖:
(3)動態執行時裝入方式(動態重定位)
只是把相對地址到絕對地址的轉換推遲到程式真正執行時才進行
總結: