地址無關代碼

地址無關代碼

在計算機領域中,地址無關代碼 (position-independent code,PIC),又稱地址無關執行檔 (position-independent executable,PIE) ,是指可在主存儲器中任意位置正確地運行,而不受其絕對地址影響的一種機器碼。PIC廣泛使用於共享庫,使得同一個庫中的代碼能夠被載入到不同進程的地址空間中。PIC還用於缺少記憶體管理單元的計算機系統中,使得作業系統能夠在單一的地址空間中將不同的運行程式隔離開來。

定義

地址無關代碼(PIC)是指運行和放置地址無關的代碼。 其實這裡PIC是一個相對意思,因為生成代碼或多或少都使用了位置無關代碼,該實現的基本思想是:把指令中需要修改的部分分離出來,跟數據部分放在一起,這樣指令部分就可以保持不變,而數據部分則在每個進程擁有一個副本。地址無關代碼能夠在不做修改的情況下被複製到記憶體中的任意位置。這一點不同於重定位代碼,因為重定位代碼需要經過連結器或載入器的特殊處理才能確定合適的運行時記憶體地址。 地址無關代碼需要在原始碼級別遵循一套特定的語義,並且需要編譯器的支持。那些引用了絕對記憶體地址的指令(比如絕對跳轉指令)必須被替換為PC相對定址指令。這些間接處理過程可能導致PIC的運行效率下降,但是大多數處理器對PIC都有很好的支持,使得這效率上的這一點點下降基本可以忽略。

動態庫

動態庫又稱動態程式庫英文為DLL,是Dynamic Link Library 的縮寫形式,DLL是一個包含可由多個程式同時使用的代碼和數據的庫,DLL不是執行檔。動態連結提供了一種方法,使進程可以調用不屬於其可執行代碼的函式。動態程式庫和動態連結是重要的軟體運行機制,它既是多個進程共享資源的主要方式,也是作業系統向應用程式提供系統服務的主要手段。動態連結主要有2個特點:動態的載入,當運行模組在需要的時候才將動態程式庫載入映射入運行模組的虛擬地址空間;動態的解析,只有當要調用的函式被調用的時候,才會把這個函式在虛擬記憶體空間的起始地址解析出來。除了資源共享這個最基本的目的之外,利用動態連結機制還可實現共享庫重定向等重要套用。動態庫一般存放系統運行過程中所產生的所有信息、原始數據、用戶輸入的信息、推理的中間結果以及推理過程的紀錄 。

例如Linux下的動態程式庫檔案是ELF格式的。Linux的動態連結實現機制引入了全局偏移 表和過程連結表,實現了位置無關代碼(PIC)。同時,ELF檔案的分層管理模型在Linux 動態連結機制中也起著重要的作用。ELF 格式的共享庫使用 PIC 技術使代碼和數據的引用與地址無關,程式可以被載入到地址空間的任意位置。PIC 在代碼中的跳轉和分支指令不使用絕對地址。PIC 在 ELF 可執行映像的數據段中建立一個存放所有全局變數指針的全局偏移量表。

引用問題

與地址無關的代碼,也就是需要考慮代碼中會對地址進行引用的情況,共享對象(GCC中的動態連結檔案)中地址引用可以分為以下幾種情況:模組內函式調用、跳轉等、模組內數據的訪問,如模組內定義的靜態變數,全局變數等、模組外部的函式調用、跳轉等和模組外部的數據的訪問,比如別的模組定義的全局變數。

模組(動態連結檔案)內部的函式的調用:由於此時調用者與被調者都是位於同一個模組,所以調用者與被調者之間的相對位置是固定的,因此,對被調者的調用就可以使用相對地址來替代絕對地址,對於這種指令就是不需要重定位的。

模組內部的數據調用:與上面分析同理,由於數據定義與引用指令是位於同一個模組的,因此它們之間的相對位置是固定的。但是此時有一些區別,現代體系結構中,數據的相對定址沒有基於當前指令的定址方式,因此ELF採用了一個巧妙的方法來獲取當前PC(程式計數器)的值,再在該基礎上添加一個偏移,即可訪問到變數。

模組外部的函式的調用:此時對外部符號的引用顯然是與地址有關的,按照先前說的基本思想,此時需要將與地址相關的部分放到數據段里。ELF 的做法是在數據段中建立一個指向這些函式的指針數組,也即是全局偏移表(GOT,Global Offset Tabel),當代碼需要引用這些外部函式時,則可以通過GOT 中的相對應的項間接引用。動態連結器在裝載模組的時候會查找每個函式所在地址,並填充GOT中的各個表項,以保證每個指針均指向正確的地址。同時由於GOT本身是放在數據段的,因此它可以在模組裝載的時候被修改,並且每個進程都可有自己的副本。

模組外部的數據的調用:該方法與模組外部的函式訪問方法相同,同樣引入 GOT ,只是此時GOT 的表項中存儲的是變數的地址。

機器語言

機器語言(machine language)是一種指令集的體系。這種指令集稱為機器碼(machine code),是計算機的CPU可直接解讀的數據。機器碼有時也被稱為原生碼(Native Code),這個名詞比較強調某種程式語言或庫與運行平台相關的部分。

機器語言是用二進制代碼表示的計算機能直接識別和執行的一種機器指令的集合。它是計算機的設計者通過計算機的硬體結構賦予計算機的操作功能。機器語言具有靈活、直接執行和速度快等特點。不同種類的計算機其機器語言是不相通的,按某種計算機的機器指令編制的程式不能在另一種計算機上執行。

要用機器語言編寫程式,編程人員需首先熟記所用計算機的全部指令代碼和代碼的涵義。手編程式時,程式設計師要自己處理每條指令和每一數據的存儲分配和輸入輸出,還需記住編程過程中每步所使用的工作單元處在何種狀態。這是一件十分繁瑣的工作,編寫程式花費的時間往往是實際運行時間的幾十倍或幾百倍。而且,這樣編寫出的程式完全是0與1的指令代碼,可讀性差且容易出錯。在現今,除了計算機生產廠家的專業人員外,絕大多數程式設計師已經不再學習機器語言。

相關詞條

熱門詞條

聯絡我們