在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

3天內不再提示

如何將一個用戶源程序變為一個可在內存中執行的程序

Q4MP_gh_c472c21 ? 來源:CSDN博客 ? 作者:hguisu ? 2021-11-11 11:19 ? 次閱讀

一、地址概念和程序如何運行在多道程序環境下,要使程序運行,必須先為之創建進程。而創建進程的第一件事,便是將程序和數據裝入內存。如何將一個用戶源程序變為一個可在內存中執行的程序,通常都要經過以下幾個步驟:

首先是要編譯:

由編譯程序(Compiler)將用戶源代碼編譯成cpu可執行的目標代碼,產生了若干個目標模塊(Object Module)(即若干程序段)。形成的目標代碼,每個目標代碼都是以0為基址順序進行編址,原來用符號名訪問的單元用具體的數據——單元號取代。這樣生成的目標程序占據一定的地址空間,稱為作業的邏輯地址空間,簡稱邏輯空間。

在邏輯空間中每條指令的地址和指令中要訪問的操作數地址統稱為邏輯地址 。很簡單,邏輯地址就是你源程序里使用的地址,或者源代碼經過編譯以后編譯器將一些標號,變量轉換成的地址。

其次是鏈接

由鏈接程序(Linker)將編譯后形成的一組目標模塊(程序段),以及它們所需要的庫函數鏈接在一起,形成一個完整的裝入模塊(Load Module);

最后是裝入(地址重定位)

由裝入程序(Loader)將裝入模塊裝入物理內存。物理內存是真實存在的插在主板內存槽上的內存條的容量的大小。

物理內存內存是由若干個存儲單元組成的,每個存儲單元有一個編號,這種編號可唯一標識一個存儲單元,稱為內存地址(或物理地址)。我們可以把內存看成一個從0字節一直到內存最大容量逐字節編號的存儲單元數組,即每個存儲單元與內存地址的編號相對應。

裝入模塊雖然具有統一的地址空間,但它仍是以“0”作為參考地址,即是浮動的。要把它裝入內存執行,就要確定裝入內存的實際物理地址,并修改程序中與 地址有關的代碼,這一過程叫做地址重定位。地址重定位主要是把邏輯地址轉換成物理內存絕對地址,這個工作又稱為地址映射。

圖 4-2 示出了這樣的三步過程。

d90d2be2-4244-11ec-b939-dac502259ad0.jpg

圖4-2 對用戶程序的處理步驟

二。 程序的鏈接源程序經過編譯后,可得到一組目標模塊,再利用鏈接程序將這組目標模塊鏈接,形成裝入模塊。根據鏈接時間的不同,可把鏈接分成如下三種:

(1) 、 靜態鏈接。在程序運行之前,先將各目標模塊及它們所需的庫函數,鏈接成一個完整的裝配模塊,以后不再拆開。我們把這種事先進行鏈接的方式稱為靜態鏈接方式。

(2)、 裝入時動態鏈接。這是指將用戶源程序編譯后所得到的一組目標模塊,在裝入內存時,采用邊裝入邊鏈接的鏈接方式。

(3)、 運行時動態鏈接。這是指對某些目標模塊的鏈接,是在程序執行中需要該(目標)模塊時,才對它進行的鏈接。

1.靜態鏈接方式(Static Linking)

我們通過一個例子來說明在實現靜態鏈接時應解決的一些問題。在圖 4-4(a)中示出了經過編譯后所得到的三個目標模塊A、B、C,它們的長度分別為 L、M和N。在模塊A中有一條語句CALL B,用于調用模塊B。在模塊B中有一條語句CALL C,用于調用模塊C。B和C都屬于外部調用符號,在將這幾個目標模塊裝配成一個裝入模塊時,須解決以下兩個問題:

(1) 對相對地址進行修改。在由編譯程序所產生的所有目標模塊中,使用的都是相對地址,其起始地址都為 0,每個模塊中的地址都是相對于起始地址計算的。

在鏈接成一個裝入模塊后,原模塊B和 C在裝入模塊的起始地址不再是 0,而分別是 L和 L+M,所以此時須修改模塊B和C中的相對地址,即把原B中的所有相對地址都加上 L,把原 C中的所有相對地址都加上L+M。

(2) 變換外部調用符號。將每個模塊中所用的外部調用符號也都變換為相對地址,如把B 的起始地址變換為 L,把 C 的起始地址變換為 L+M,如圖 4-4(b)所示。

這種先進行鏈接所形成的一個完整的裝入模塊,又稱為可執行文件。通常都不再拆開它,要運行時可直接將它裝入內存。這種事先進行鏈接,以后不再拆開的鏈接方式,稱為靜態鏈接方式。

d94308e8-4244-11ec-b939-dac502259ad0.jpg

圖 4-4 程序鏈接示意圖

2.裝入時動態鏈接(Load-time Dynamic Linking)

用戶源程序經編譯后所得的目標模塊,是在裝入內存時邊裝入邊鏈接的,即在裝入一個目標模塊時,若發生一個外部模塊調用事件,將引起裝入程序去找出相應的外部目標模塊,并將它裝入內存,還要按照圖4-4所示的方式來修改目標模塊中的相對地址。裝入時動態鏈接方式有以下優點:

(1) 、 便于修改和更新。對于經靜態鏈接裝配在一起的裝入模塊,如果要修改或更新其中的某個目標模塊,則要求重新打開裝入模塊。這不僅是低效的,而且有時是不可能的。若采用動態鏈接方式,由于各目標模塊是分開存放的,所以要修改或更新各目標模塊是件非常容易的事。

(2)、 便于實現對目標模塊的共享。在采用靜態鏈接方式時,每個應用模塊都必須含有其目標模塊的拷貝,無法實現對目標模塊的共享。但采用裝入時動態鏈接方式,OS則很容易將一個目標模塊鏈接到幾個應用模塊上,實現多個應用程序對該模塊的共享。

3.運行時動態鏈接(Run-time Dynamic Linking)

在許多情況下,應用程序在運行時,每次要運行的模塊可能是不相同的。但由于事先無法知道本次要運行哪些模塊,故只能是將所有可能要運行到的模塊都全部裝入內存,并在裝入時全部鏈接在一起。顯然這是低效的,因為往往會有些目標模塊根本就不運行。

比較典型的例子是作為錯誤處理用的目標模塊,如果程序在整個運行過程中都不出現錯誤,則顯然就不會用到該模塊。近幾年流行起來的運行時動態鏈接方式,是對上述在裝入時鏈接方式的一種改進。

這種鏈接方式是將對某些模塊的鏈接推遲到程序執行時才進行鏈接,亦即,在執行過程中,當發現一個被調用模塊尚未裝入內存時,立即由OS去找到該模塊并將之裝入內存,把它鏈接到調用者模塊上。凡在執行過程中未被用到的目標模塊,都不會被調入內存和被鏈接到裝入模塊上,這樣不僅可加快程序的裝入過程,而且可節省大量的內存空間。

三。 程序的裝入(地址的變換)為了闡述上的方便,我們先介紹一個無需進行鏈接的單個目標模塊的裝入過程。該目標模塊也就是裝入模塊。在將一個裝入模塊裝入內存時,可以有絕對裝入方式、可重定位裝入方式和動態運行時裝入方式,下面分別簡述之。

1.絕對裝入方式(Absolute Loading Mode)

在編譯時,如果知道程序將駐留在內存的什么位置,那么,編譯程序將產生絕對地址的目標代碼。即按照物理內存的位置賦予實際的物理地址。例如,事先已知用戶程序(進程)駐留在從R處開始的位置,則編譯程序所產生的目標模塊(即裝入模塊)便從R處開始向上擴展。

絕對裝入程序按照裝入模塊中的地址,將程序和數據裝入內存。裝入模塊被裝入內存后,由于程序中的邏輯地址與實際內存地址完全相同,故不須對程序和數據的地址進行修改。程序中所使用的絕對地址,既可在編譯或匯編時給出,也可由程序員直接賦予。

這個方式的優點:是CPU執行目標代碼快。

缺點:

1)是由于內存大小限制,能裝入內存并發執行的進程數大大減少

2)編譯程序必須知道內存的當前空閑地址部分和其地址,并且把進程的不同程序段連續地存放起來,編譯非常復雜。由于程序

因此,通常是寧可在程序中采用符號地址,然后在編譯或匯編時,再將這些符號地址轉換為絕對地址。

如何把虛擬內存地址空間變換到內存唯一的一維物理線性空間?涉及到兩個問題:

一是虛擬空間的劃分問題。

二是把虛擬空間中已經鏈接和劃分好的內容裝入內存,并將虛擬空間地址映射內存地址的問題。即地址映射。地址映射就是建立虛擬地址與內存地址的關系。

2.靜態地址重定位(可重定位裝入方式 Relocation Loading Mode)

絕對裝入方式只能將目標模塊裝入到內存中事先指定的位置。在多道程序環境下,編譯程序不可能預知所編譯的目標模塊應放在內存的何處,因此,絕對裝入方式只適用于單道程序環境。

在多道程序環境下,所得到的目標模塊的起始地址通常是從 0 開始的,程序中的其它地址也都是相對于起始地址計算的。此時應采用可重定位裝入方式,根據內存的當前情況,將裝入模塊裝入到內存的適當位置。

靜態地址重定位:即在程序裝入對目標代碼裝入內存的過程中完成,是指在程序開始運行前,程序中指令和數據的各個地址均已完成重定位,即完成虛擬地址到內存地址映射。地址變換通常是在裝入時一次完成的,以后不再改變。

值得注意的是, 在采用可重定位裝入程序將裝入模塊裝入內存后, 會使裝入模塊中的所有邏輯地址與實際裝入內存的物理地址不同,圖4-3示出了這一情況。

d969f32c-4244-11ec-b939-dac502259ad0.jpg

圖 4-3 作業裝入內存時的情況

例如,在用戶程序的 1000 號單元處有一條指令LOAD 1,2500,該指令的功能是將 2500 單元中的整數 365 取至寄存器 1。但若將該用戶程序裝入到內存的 10000~15000號單元而不進行地址變換, 則在執行11000號單元中的指令時,它將仍從 2500 號單元中把數據取至寄存器1而導致數據錯誤。

由圖4-3 可見,正確的方法應該是將取數指令中的地址 2500 修改成 12500,即把指令中的相對地址 2500 與本程序在內存中的起始地址 10000 相加,才得到正確的物理地址12500。除了數據地址應修改外,指令地址也須做同樣的修改,即將指令的相對地址 1000 與起始地址 10000 相加,得到絕對地址 11000。

優點:無需硬件支持

缺點:

1)程序重定位之后就不能在內存中搬動了;

2)要求程序的存儲空間是連續的,不能把程序放在若干個不連續的區域中。

3.動態地址重定位(動態運行時裝入方式Dynamic Run-time Loading)

可重定位裝入方式可將裝入模塊裝入到內存中任何允許的位置,故可用于多道程序環境;但這種方式并不允許程序運行時在內存中移動位置。因為,程序在內存中的移動,意味著它的物理位置發生了變化, 這時必須對程序和數據的地址(是絕對地址)進行修改后方能運行。

然而,實際情況是,在運行過程中它在內存中的位置可能經常要改變,此時就應采用動態運行時裝入的方式。

動態地址重定位:不是在程序執行之前而是在程序執行過程中進行地址變換。更確切的說,是把這種地址轉換推遲到程序真正要執行時才進行,即在每次訪問內存單元前才將要訪問的程序或數據地址變換成內存地址。

動態重定位可使裝配模塊不加任何修改而裝入內存。為使地址轉換不影響指令的執行速度,這種方式需要一個重定位寄存器的支持,

優點:

1)目標模塊裝入內存時無需任何修改,因而裝入之后再搬遷也不會影響其正確執行,這對于存儲器緊縮、解決碎片問題是極其有利的;

2)一個程序由若干個相對獨立的目標模塊組成時,每個目標模塊各裝入一個存儲區域,這些存儲區域可以不是順序相鄰的,只要各個模塊有自己對應的定位寄存器就行。

缺點:需要硬件支持。

四。 Windows NT動態鏈接庫5.1. 構造動態鏈接庫

DLL是包含函數和數據的模塊,它的調用模塊可為EXE或DLL,它由調用模塊在運行時加載;加載時,它被映射到調用進程的地址空間。在VC中有一類工程用于創建DLL。

庫程序文件 .C:相當于給出一組函數定義的源代碼;

模塊定義文件 .DEF:相當于定義鏈接選項,也可在源代碼中定義;如:DLL中函數的引入和引出(dllimport和dllexport)。

編譯程序利用 .C文件生成目標模塊 .OBJ

庫管理程序利用 .DEF文件生成DLL輸入庫 .LIB和輸出文件 .EXP

鏈接程序利用 .OBJ和 .EXP文件生成動態鏈接庫 .DLL。

5.2. DLL的裝入方法

1)裝入時動態鏈接(load-time):

編程時顯式調用某個DLL函數,該DLL函數在可執行文件中稱為引入(import)函數。

鏈接時需利用 .LIB文件。在可執行文件中為引入的每個DLL建立一個IMAGE_IMPORT_DESCRIPTOR結構。

在裝入時由系統根據該DLL映射在進程中的地址改寫Import Address Table中的各項函數指針。Hint是DLL函數在DLL文件中的序號,當DLL文件修改后,就未必指向原先的DLL函數。在裝入時,系統會查找相應DLL,并把它映射到進程地址空間,獲得DLL中各函數的入口地址,定位本進程中對這些函數的引用

裝入時動態鏈接過程:

(注:Import Address Table是在裝入時依據DLL模塊的加載位置確定)。

d98a25a2-4244-11ec-b939-dac502259ad0.png

「DLL函數的調用過程:」

d9b46b50-4244-11ec-b939-dac502259ad0.png

2)運行時動態鏈接(run-time):

在編程時通過LoadLibrary(給出DLL名稱,返回裝入和鏈接之后該DLL的句柄), FreeLibrary, GetProcAddress(其參數包括函數的符號名稱,返回該函數的入口指針)等API來使用DLL函數。這時不再需要引入庫(import library)。

LoadLibrary或LoadLibraryEx把可執行模塊映射到調用進程的地址空間,返回模塊句柄;

GetProcAddress獲得DLL中特定函數的指針,返回函數指針;

FreeLibrary把DLL模塊的引用計數減1;當引用計數為0時,拆除DLL模塊到進程地址空間的映射;

運行時動態鏈接的例子:

HINSTANCE hInstLibrary;//模塊句柄定義

DWORD (WINAPI *InstallStatusMIF)(char*, char*, char*, char*, char*, char*, char*, BOOL);//函數指針定義

if (hInstLibrary = LoadLibrary(“ismif32.dll”))//映射

{

InstallStatusMIF = (DWORD (WINAPI *)(char*,char*,char*, char*, char*, char*, char*, BOOL)) GetProcAddress(hInstLibrary, “InstallStatusMIF”);//獲得函數指針

if (InstallStatusMIF)

{

if (InstallStatusMIF(“office97”, “Microsoft”, “Office 97”, “999.999”, “ENU”, “1234”, ”Completed successfully”, TRUE) !=0)//調用DLL模塊中的函數

{

}

}

FreeLibrary(hInstLibrary);//拆除映射

}

END

作者:hguisu原文地址:https://blog.csdn.net/hguisu/article/details/5713099

責任編輯:haq

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

    關注

    8

    文章

    3043

    瀏覽量

    74194
  • 程序
    +關注

    關注

    117

    文章

    3794

    瀏覽量

    81255

原文標題:程序如何運行?編譯、鏈接、裝入?

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    不停的malloc程序會異常嗎

    用完,程序應該會異常退出。 于是我找了環境,把程序運行起來試下。 先用虛擬機,跑的 32 位的紅帽系統,
    的頭像 發表于 01-14 09:17 ?63次閱讀

    labview生成可執行程序后vi都在同路徑下嗎

    文件打包成單獨的可執行文件或安裝程序,這些VI和資源文件在內部被組織和引用,而不是作為單獨的物理文件存放在exe文件所在的文件夾
    的頭像 發表于 09-04 17:06 ?690次閱讀

    計算機進行程序控制工作的基本原理是怎樣的

    計算機程序控制是計算機科學核心概念,它涉及到計算機如何根據預設的指令序列執行任務。 1. 計算機硬件基礎 在深入
    的頭像 發表于 09-04 16:57 ?665次閱讀

    socket對應連接嗎

    在探討“socket對應連接”這命題時,我們首先需要明確socket的基本概念和它在網絡通信中的作用。Socket,即套接字,是網
    的頭像 發表于 08-16 10:55 ?542次閱讀

    要做一個GPRS遠程升級的工程,有想法不知道是否可行,請幫忙看下?

    要做一個GPRS遠程升級的工程,有想法不知道是否可行,如下: 1.上電進入IAP程序,啟動看門狗,用戶APP標志存在則跳轉,無則等等
    發表于 05-16 07:14

    隨機抽取SV數組元素方法實現

    如果想從關聯數組隨機選取元素,需要逐個訪問它之前的元素,原因是沒辦法能夠直接訪問到第N
    的頭像 發表于 03-21 10:11 ?1080次閱讀
    隨機抽取SV數組<b class='flag-5'>中</b>的<b class='flag-5'>一</b><b class='flag-5'>個</b>元素方法實現

    數組和鏈表在內存的區別 數組和鏈表的優缺點

    數組和鏈表在內存的區別 數組和鏈表的優缺點? 數組和鏈表是常見的數據結構,用于組織和存儲數據。它們在內存的存儲方式以及優缺點方面存在
    的頭像 發表于 02-21 11:30 ?1096次閱讀

    Falsh和RAM運行同段代碼,執行效率相同嗎?

    在Flash運行程序和在RAM運行程序,同段代買執行時間是不是在RAM
    發表于 02-19 07:10

    如何將HC-SR04連接到Arduino并編寫簡單的程序來測量距離

    種流行的Arduino超聲波傳感器是HC-SR04。它廣泛用于非接觸式距離測量,通常用于機器人和自動化項目。本指南向您展示如何將HC-SR04連接到Arduino并編寫
    的頭像 發表于 02-11 10:17 ?2442次閱讀
    <b class='flag-5'>如何將</b>HC-SR04連接到Arduino并編寫<b class='flag-5'>一</b><b class='flag-5'>個</b>簡單的<b class='flag-5'>程序</b>來測量距離

    如何將增量旋轉編碼器與Arduino連接

    在本教程,您將學習如何將增量旋轉編碼器與Arduino連接,以讀取旋鈕的運動。這對于在機器人和其他應用程序創建用戶界面或讀取機械位置非常
    的頭像 發表于 02-11 10:00 ?1548次閱讀
    <b class='flag-5'>如何將</b>增量旋轉編碼器與Arduino連接

    CYT4BF通過分配ITCM內存來使用經常執行的代碼,下載程序時報錯的原因?

    正常,但是下載程序時出現總線錯誤。 Q1) 總線錯誤是否因為ITCM內存地址與ROM地址重疊而發生? Q2) 您 CAN 告訴我如何將常用代碼分配給 ITCM 內存并使用它? 問
    發表于 01-31 06:34

    CYBLE-416045-02如何將NAR設置寫入SFLASH?

    在 sFlash 配置 NAR 設置。 我已經在引導加載程序代碼這樣做了,如下所示: 我生成了由引導加載
    發表于 01-29 06:50

    在SWAP模式下編輯lsl文件,如何將分區A和B中程序的lsl文件轉換為lsl文件?

    啟用交換模式后,如何將分區 A 和 B 中程序的 lsl 文件轉換為 lsl 文件? 或者我們可以 AB 分區
    發表于 01-25 07:46

    如何將共享代碼映射到DSPR5以及將其映射到其他RAM區域?

    你好, 我正在開發 Erika 多核項目,該項目旨在在裝有 TASKING v6.2r2 編譯器的 TC397XE 處理器上執行。 目前,我專注于前 4 內核,我的應用
    發表于 01-24 07:26

    程序增加變量導致異常的分析

    大家在平常的編程過程應該會碰到各種奇葩的問題吧,反正我最近是碰到了次,再此跟大家分享下。事情的原因是我在程序增加了
    的頭像 發表于 01-22 09:56 ?626次閱讀
    <b class='flag-5'>程序</b><b class='flag-5'>中</b>增加<b class='flag-5'>一</b><b class='flag-5'>個</b>變量導致異常的分析
    主站蜘蛛池模板: 丁香婷婷在线| 69日本xxxhd| 夜间免费视频| 亚洲免费一级视频| 特污兔午夜影院| 九九热最新| 69精品久久久久| 91在线免费看| 男男污肉高h坐便器调教| 尤物黄色| 天天看爽片| 免费两性的视频网站| 国产精品欧美一区二区三区| 一本久草| 你懂得国产| 波多野结衣在线观看一区| 成人www视频| 午夜免费视频观看| 国产午夜精品理论片| 91成人在线免费视频| 国产精品高清免费网站| 天堂最新版资源www在线| 男人的天堂在线免费视频| 国产成人a| 欧美黄色成人| 757福利影院合集3000| 一级做a爰片久久毛片人呢| 色偷偷亚洲男人| 黄色工厂在线播放| 午夜国产精品视频| vip影视免费观看| 国产高清在线精品一区| 三级黄色片在线播放| 国产精品天天爽夜夜欢张柏芝| 午夜 福利| 欧美涩区| 亚洲日韩色综合视频| 免费人成年激情视频在线观看| 91色在线视频| 亚洲小便| 亚洲欧美在线播放|