兩個地址都是虛擬地址。
lma: 加載地址,如加載到RAM中等,在嵌入式中,有可能是在ROM中(這時LMA!=VMA)
vma: 虛擬地址,就是程序運行時的地址,一般就是內(nèi)存地址,如要把ROM中的數(shù)據(jù)加載到RAM中運行。
Linker,鏈接器的作用: 1。將LMA寫到(可執(zhí)行的)二進制文件里面去 2。解析符號。即,把不同的符號,根據(jù)符號表中的信息,轉(zhuǎn)換成對應(yīng)的地址。此處只涉及VMA,即程序運行時候的地址。 Loader,裝載器的作用: 1。從二進制文件中讀出對應(yīng)的段的信息,比如text,data,bss等段的信息, 將內(nèi)容拷貝到對應(yīng)的LMA的地址處。此謂,裝載(對應(yīng)內(nèi)容)到裝載地址(LMA)。 2。如果發(fā)現(xiàn)VMA!=LMA, 即 程序運行時候的地址,和剛剛把程序內(nèi)容拷貝到的地址LMA,兩者不一樣, 那么就要把對應(yīng)的內(nèi)容,此處主要是data,數(shù)據(jù)段的內(nèi)容,從剛剛裝載到的位置,LMA處,拷貝到VMA處, 這樣,程序運行的時候,才能夠在執(zhí)行的時候,找到對應(yīng)的VMA處的變量,才能找到對應(yīng)的值,程序才能正常運行。 一般情況下是LMA = VMA,只有小數(shù)情況是不相等:
CPU
從ROM,比如常見的Nor
Flash中讀取代碼的速度,要遠遠小于從RAM,比如常見的SDRAM,中讀取的速度,所以,才會牽扯到將代碼燒寫到ROM里面,然后代碼的最開始,將
此部分程序reaload,重載,也就是從此處的ROM的地址,即LMA,重新拷貝到SDRAM中去,也就是VMA的地方,然后從那里運行。
//
詳解LMA(裝載內(nèi)存地址)與VMA(虛擬內(nèi)存地址)
version: 20091004 author: green-waste@163.com 關(guān)于LMA和VMA,這個問題,有點點小復(fù)雜,不過,此處,我會把我的理解,盡量通過通俗的方式解釋出來,以方便理解。當(dāng)然,鄙人水平有限,難免有錯,希望各位批評指正。 一般提及LMA和VMA,多數(shù)情況都是和ld,鏈接器相關(guān)的。 在了解這兩個名詞的詳細含義之前,有些基本知識和前提要說一下: [基礎(chǔ)知識] 1。從你寫的源代碼到執(zhí)行你的程序,一般經(jīng)歷了這幾個過程: 源代碼編輯 -> 編譯 -> 鏈接 -> 裝載 -> 執(zhí)行 2。編譯,簡單說就是用編譯工具,將你的源碼,變成可以執(zhí)行的二進制代碼,也叫做目標(biāo)文件,當(dāng)然只是對應(yīng)某一種硬件平臺,比如此處我用的是Intel的X86系列的CPU,編譯出來的,就是針對X86的二進制代碼。 3。鏈接就是,將多個目標(biāo)文件合并為一個目標(biāo)文件,稱作可執(zhí)行文件。 4。每個目標(biāo)文件都包含一連串的section,最常見,最基礎(chǔ)的至少有: .text,代碼段,就是CPU要運行的指令代碼; .data,數(shù)據(jù)段,程序中包含的一些數(shù)據(jù),放在這個段里; .bss, 未初始化段,記錄了程序里有哪些未初始化的變量,就相當(dāng)于只記錄對應(yīng)的名字,留著程序運行前去初始化為0,所以,此處并不占用具體空間。打個比方就是,只 記錄人名,沒有人站在這里占地方,而對應(yīng)的.text和.data段,都是既有人名(函數(shù)或者變量名),又占對應(yīng)的地方(包含具體空間記錄到底是什么指令 代碼和數(shù)據(jù)的數(shù)值是多少)。 5。section一般可以分為loadable與allocatable. 通俗點說就是: loadable,可加載,就是,原先目標(biāo)文件里面包含對應(yīng)的代碼或數(shù)據(jù),所以,裝載器要把這些內(nèi)容,load到對應(yīng)的地址,以便程序可以運行; 而allocatable,可分配的,最簡單理解就是上面提到的.bss段,那里記錄了人名,到時候,你要給這些人名分配空間給你站的地方,對應(yīng)著也就是變量所要占用的具體內(nèi)存空間了。 其他還有既不是loadbale的,也不是allocatable的,比如只存儲debug信息的段,此處不多解釋。 [前提] 程序已經(jīng)編譯好了,有了一個可執(zhí)行文件,也叫目標(biāo)文件,二進制文件,才會有后面的把程序裝載,運行的事情。 看完了基礎(chǔ)知識和前提,再說我們此處的主題,才能更加清楚是咋回事: 對于目標(biāo)文件中的loadable或allocatable的section,其都有兩個地址:VMA 和 LMA 。 知道了其來由,再看具體解釋: [LMA 詳解] LMA的英文原版解釋: LMA(Load Memory Address): the address at which the section will be loaded. 什么是Load Memory Address,內(nèi)存裝載地址呢? 此處,單單從名字上,我們就可以看出幾層意思: 1。load,裝載 為何要裝載呢? 因為,如果想要使你的程序(即經(jīng)歷過,由你的源碼,通過編譯器的編譯,鏈接器的鏈接,形成的那個可執(zhí)行文件),能在內(nèi)存里面運行,那么肯定涉及到一點,就是,有人,把你的這個程序, ,從此處常見的存儲器硬盤里面,搬到內(nèi)存里面去了,然后才有可能運行。而這里的裝載,就是對應(yīng)這個意思。就是把程序,從硬盤里面,裝載Load,到內(nèi)存里面去了。 對應(yīng)地,放到內(nèi)存哪里去了呢?就是LMA,Load Memory Address,就是把你的程序中的對應(yīng)的內(nèi)容,詳細點說就是,把其中的.text代碼段,.data數(shù)據(jù)段等內(nèi)容,搬到,也就是copy拷貝到,內(nèi)存的LMA地址處了。 2。Memory,內(nèi)存 上面已經(jīng)解釋了,這里再多說幾句。 程序運行的本質(zhì),就是CPU讀取到指令,然后執(zhí)行。這里就涉及到,如果想要你的程序運行, 首先,你應(yīng)該把對應(yīng)的指令,放到合適的地方,CPU 才能讀到,才能執(zhí)行。 此 處合適的地方,有人想到,直接放到硬盤這里,CPU過來讀取,然后執(zhí)行不就可以了嗎,還不用這么麻煩地將(指令)代碼搬來搬去的,多省事。但是實際上,系 統(tǒng)就是這么“笨”地搬來搬去,原因在于,從硬盤上直接讀取指令,速度比直接從內(nèi)存,一般PC 上是各種類型的RAM,比如DDR,此處統(tǒng)稱為Memory/內(nèi)存, 要慢很多倍,所以,系統(tǒng)才會不嫌棄麻煩,把代碼拷貝到內(nèi)存里面去,然后從內(nèi)存里面讀取指令,然后執(zhí)行,這樣效率會高很多。 所以,此處簡單說就是,為了總體效率,對于普通系統(tǒng),比如PC,程序的執(zhí)行都是在Memory,內(nèi)存里面執(zhí)行的。 因此,用一句話總結(jié)就是: 代碼被裝載到內(nèi)存的某個地方,那個地方的地址,就是LMA 。 [VMA 詳解] 英文解釋: VMA(Virtual Memory Address):the address the section will have when the output file is run; 那啥是虛擬內(nèi)存地址呢?簡單說就是,你程序運行時候的所對應(yīng)的地址。 此處所謂的虛擬,一般來說,指的是啟用了MMU之后,才有了虛擬地址和實地址。 此處,我們可以簡單的理解為,就是內(nèi)存的實際地址即可。 程序運行前,要把程序的內(nèi)容,拷貝到對應(yīng)的內(nèi)存地址處,然后才能運行的。 因此,一句話總結(jié)就是: 代碼要運行的時候,此時對應(yīng)的地址,就是VMA。 [理解此句:在多數(shù)情況下,LMA和VMA是相等的] 這句話,說白了,可以(武斷地)這么理解: 如果是普通PC電腦,也就是上面說的,大多數(shù)情況下,那么LMA和VMA是一樣的,也就是,程序被加載到內(nèi)存的什么地方,也就在什么地方運行。 如果是嵌入式系統(tǒng),也就是相對的“少數(shù)情況”,LMA和VMA不一樣。而其中最常見的一種情況就是, 程序被放到ROM中,比如設(shè)置為只讀的Nor Flash中,也就是LMA的地址是Nor Flash的地址, 此 如隨便舉例為0x10000000,而程序要運行時候的地址是內(nèi)存地址,比如0x30000000,也就是VMA 是0x30000000,這時候,就要我們自己保證,在程序運行之前,把自己的程序,從LMA=0x10000000拷貝到VMA=0x3000000 處,然后程序才可以正常運行。 有人會問,反正對于ROM來說,CPU 也是可以直接從ROM里面讀取代碼,然后運行的。為何還要前面提到的,弄個LMA 和VMA不同,搬來搬去的呢?因為ROM,顧名思義,是只讀的,只能讀取,不能寫入的。 而程序中的代碼段,由于只是被讀取,不涉及到修改寫入,是沒有問題的。但是對于數(shù)據(jù)段和bss位初始化段來說,里面的所有的程序的變量,多數(shù)都是在運行的時候,不僅要讀取,而且要被修改成新的值,然后寫入新的值的,所以,如果還是放到ROM里面,就沒法修改寫入了。 而 且,另一個原因是,CPU從ROM,比如常見的Nor Flash中讀取代碼的速度,要遠遠小于從RAM,比如常見的SDRAM,中讀取的速度,所以,才會牽扯到將代碼燒寫到ROM里面,然后代碼的最開始,將 此部分程序reaload,重載,也就是從此處的ROM的地址,即LMA,重新拷貝到SDRAM中去,也就是VMA的地方,然后從那里運行。 [后記] 關(guān)于LMA 和 VMA: Linker,鏈接器的作用: 1。將LMA寫到(可執(zhí)行的)二進制文件里面去 2。解析符號。即,把不同的符號,根據(jù)符號表中的信息,轉(zhuǎn)換成對應(yīng)的地址。此處只涉及VMA,即程序運行時候的地址。 Loader,裝載器的作用: 1。從二進制文件中讀出對應(yīng)的段的信息,比如text,data,bss等段的信息, 將內(nèi)容拷貝到對應(yīng)的LMA的地址處。此謂,裝載(對應(yīng)內(nèi)容)到裝載地址(LMA)。 2。如果發(fā)現(xiàn)VMA!=LMA, 即 程序運行時候的地址,和剛剛把程序內(nèi)容拷貝到的地址LMA,兩者不一樣, 那么就要把對應(yīng)的內(nèi)容,此處主要是data,數(shù)據(jù)段的內(nèi)容,從剛剛裝載到的位置,LMA處,拷貝到VMA處, 這樣,程序運行的時候,才能夠在執(zhí)行的時候,找到對應(yīng)的VMA處的變量,才能找到對應(yīng)的值,程序才能正常運行。 |
|