1·什麼是CMD文件,它有什麼做用。sass
CMD文件是用來講明對應的對應的代碼、數據、變量的存放空間。安全
它包括兩個指令SECTOINS和MEMORY。oop
若是把RAM和ROM當作是兩個倉庫的話,那MEMORY指令就是把這兩個倉庫再分紅不一樣的區域。若是把不一樣的代碼段是當作一件件貨物的話,那麼SECTOINS指令則指出了這些貨物對應的存放位置。ui
.cmd文件調試
由彙編器產生的COFF格式的OBJ文件中的段做爲構造塊,當有多個文件進行連接時,連接器會將輸入段結全在一塊兒產生可執行的COFF輸出模塊,而後連接器爲各輸出段選擇存儲器地址。ci
1.1 MEMORY指令說明input
存儲器(MEMORY)僞指令,用來定義目標系統的存儲器空間。MEMORY能夠定義存儲器的區域,並指定起始地址和長度。cmd
MEMORY僞指令的通常語法:flash
MEMORYit
{
PAGE 0: name1[(attr)]:origin=constant, length=constant;
PAGE n: name1[(attr)]:origin=constant, length=constant;
}
PAGEn中的頁號n最大爲255。每一個PAGE表明一個徹底獨立的地址空間。一般PAGE0爲程序存儲器,PAGE1爲數據存儲器。
Name1:存儲器區間名。可包含8個字符。不一樣PAGE能夠取一樣的name1,但在同一個PAGE內區間名不能夠相同。
Attr:可選項。規定存儲器屬性。
R,能夠對存儲器執行讀操做
W,能夠對存儲器執行寫操做
X,破除能夠裝入可執行的程序代碼
I,規定能夠對存儲器進行初始化
Origin:起始地址。
Length:區間長度。
初始化段用SECTIONS可定位兩次:裝入和運行。如:一些關鍵的執行代碼必須裝在系統的ROM中,但但願在較快的RAM中運行。
未初始化段只可被定位一次。
本身寫的關於LF2406A的.cmd文件
MEMORY
{
PAGE 0: VECS: origin=0h, length=40h ;中斷向量表,40h~43h爲安全代碼
;或保留代碼區,復位向量是0h和1h
FLASH: origin=44h, length=0ffbch ;32Kflash
SARAM: origin=8000h, length=800h ;當PON=1&&DON=0,
;SARAM映射爲程序存儲空間
B0: origin=ff00h, length=100h ; 256 WORD DARAM,CNF=1時
PAGE 1: MMRS: origin=0h, length=60h ;內部映射寄存器,或保留區間
B2: origin=60h, length=20h ;32 WORD DARAM
B0: origin=200h, length=100h ;256 WORD DARAM,CNF=0時
B1: origin=300h, length=100h ;256 WORD DARAM
SARAM: origin=800h, length=800h ;2K WORD SARAM,DON=1&&PON=0
PF1: origin=7000, length=230h ;外設幀1
EVA: origin=7400, length=32h ;外設幀2
EVB: origin=7500, length=32h ;外設幀3
}
內部的全部的存儲器都定義過了,最後的三個PF一、EVA、EVB能夠不用定義的,由於是這外設的寄存器映射。
1.2 SECTOINS指令說明
段(SECTOINS)僞指令,告訴連接器如何將輸入段結合成輸出段並告訴連接器將輸出段放在存儲器的何處。
SECTIONS
{
Name:[property,property,…]
Name:[property,property,…]
Name:[property,property,…]
}
Name:源程序中的段名。如.text
Property:段的屬性參數。一個段的屬性參數包括下列五種:
1.2.1 Load allocation,由它定義將輸出段加載到存儲器中的什麼位置。
語法:load: allocation、allocation、>allocation (allocation是將邏輯段定位的地址說明)
例如:.text: load=0x1000 ;將輸出段定位到一個特定的地址
.text: load>ROM ;將輸出段定位到命名爲ROM的存儲區
.text: align=0x80 ;關鍵詞align規定輸出段.text定位到從地址邊界0x80開始
.text: block(128) ;關鍵詞bolck規定段必須在兩個地址邊界以內,若是段太
;大,就從一個地址邊界開始
.text: PAGE0 ;將輸出段定位到PAGE0
若是輸出段只定位一個位置,則可省去關鍵字load。如:.text: >ROM
若是要用到一個以上參數,能夠將它們排成一行。如:.text: >ROM align 16 PAGE 2
或.text: load(ROM align(16) PAGE(2))
(地址邊界是2的N次方冪的地址,如地址邊界定爲16,則其地址爲xxx0h。)
定邊界地址用在什麼狀況下?
1.2.2 Run allocation,由它定義輸出段在存儲器的什麼位置開始運行。
語法:run=allocation或run>allocation
連接器爲每一個輸出段在目標存儲器中分配兩個地址:加載地址和執行地址。一般這兩個地址是相同的。但如要先將程序加載到ROM,而後在RAM中以較快的速度運行。則可兩次定位,如:
.fir: load=ROM,run=RAM
1.2.3 Input sections,由它定義哪些輸入段組成輸出段。
語法:{input_sections}
.text: {*(.text)} 等價於 .text: {}
這樣就把全部的.text段連接成.text段輸出。
也能夠明確的用文件名和段名來肯定輸入段:
.text:
{
F1.obj (.text,sect) ;連接F1.obj的.text、.sect段
F2.obj (sect) ;這裏的sect前面的點是原本就不用寫仍是書上的錯誤?
F3.obj ;連接f3.obj的全部段
}
1.2.4 Section type,用它爲輸出段定義特殊形式的標誌
語法:Type=COPY、Type= DSECT、Type=NOLOAD
1.2.5 Fill value,當初始化段中存在未初始化的存儲區間時,對其填充一指定值。
語法:fill: value 或name:…{…}=value
1.3問題
1.3.1若是不一樣頁中定義了相同的名字,又不指定PROG,這時默認在哪一個空間呢?
如:PAGE 0: B0: origin=0ff00h, length=100h ; 256 WORD DARAM,CNF=1時
PAGE 1: B0: origin=200h, length=100h ;256 WORD DARAM,CNF=0時
這明 .const: {} >B1 是指向那個空間?
1.3.2
-o file.out
-m file.map
以上兩個語句用來生成.out和.map文件。若是沒寫這,也沒有關係,CCS->project->Build options菜單下的Linker選項頁裏面還能夠設置。
2·代碼中關於對段的定義
對段定義目的:上面已經說明了CMD文件的做用是倉庫分區和指訂貨物的存放位置,而對代碼中段的定義則是給代碼,數據,變量這些貨物起名字,使它對應CMD文件裏的段名存放。
2.1 段的分類
2.1.1目標文件至少包含三個默認段:
.text 文本段 一般包含可執行代碼
.data 數據段 一般包含初始化的數據
.bss 保留空間段 一般爲沒有初始化的變量保留空間
2.1.2自定義段:
.usect 保留空間段 爲沒有初始化的數據保留空間的自定義段
.sect 初始化段 自定義段
和默認段的使用相同,但它們被單獨彙編。例如,重複使用.text段在目標文件中建立單個.text段,在連接時,這個.text段做爲單個單元分配到存儲器中。假中有一部分可執行代碼(如初始化程序)不但願和.text段分配在一塊兒,能夠將它們彙編進一個自定義段,這樣就能夠分配在與.text段不一樣的地方。
不能用不一樣的僞指令定義相同的段。如.usect和.sect用同一個段名。
2.1.3初始化段
.text
.data
.sect 「section name(段名)」
當彙編器第一次遇到一個.data時,.data段爲空的。跟在第一個.data僞指令後的指令被彙編進.data段,直到遇到.text、.sect、.asect。若是後面還遇到.data,則將跟在這些.data後面的語句彙編時已經存在的.data段。這樣就造成了單個可被連續分配到存儲器中的.data段。
2.1.4未初始化段
.bss symbol(符號), size in words(字數)[blocking flag]
symbol .usect 「section name(段名)」size in words,[blocking flag]
symbol:指向.bss或.usect僞指令所保留的存儲空間的第一個字。這個符號與保留空間所使用的變量名相對應。這個符號可讓其化段引用,而且也能夠用一個全局符號(.global)來聲明。
至關於C中定義 unsigned char symbol[size in words];
Size in words:保留空間大小。
Blocking flag:可選項。若是該參數指定一個大於0的值,則彙編器會將size in words指定的字數連續存放,分配的空間不跨頁面的邊界,除非字數超過一頁的長度,此時將從一個頁面邊界開始。
Section name:爲保留空間的自定義段的段名。0~8個字符。最多可產生32767個不一樣的自定義段。
和symbol有什麼不一樣?
段名是用來彙編器聯接用的,程序裏用不到;而符號是地址,程序裏能夠引用。
自定義的段名第一個字符也能夠是 . ,如:sect 「.cinit」。
初始化段定義僞指令告訴彙編器中止彙編進入當前的段,而開始彙編進入指定的段,但未初始化段定義僞指令不終止當前的段而開始一個新段,它們只是簡間的臨時離開當前的段。因此.bss和.usect能夠出如今初始化段的任何地方而不會影響它的內容。
2.1.5 做用
連接器將段從新定位到目標系統的存儲器映射。大多數系統包含幾種存儲器,使用段可使目標存儲器的使用更爲有效。全部段均可獨立地從新定位,可將任意段放到目標存儲器任何已經分配的塊。
2.2 問題
2.2.1
.data
Coeff .word 011h,022h,033h
.bss var1,1
.bss buffer,10
Ptr .word 0123
.text
Add: LAC 0FH
Aloop: SBLK 1
BLEZ aloop
SACL var1,0
.data
Ivals .word 0aah,0bbh
Var2 .usect 「newvars」,1
Inbuf .usect 「newvars」,7
.text
ADD #0FFH
.text 7(WORDS)
.data 5
.bss 11
.newvars 8(由.usect建立的段)
在兩本書中看到這個例子,其中.data段都是5個字的目標碼。
Ptr .word 0123不算是.data段嗎?那是什麼段?爲何沒有計算進去,是書上寫錯了?
查看.map文件,能夠看出.data 段是6個字的目標碼,應該是書本錯了。
2.2.2
編譯鏈接都經過,爲何生成的.out文件沒法下載,提示0x0地址數據錯誤。
查看Disassembly,8000h前面的數據全爲FF,8000h~87ffh即SARAM區裏有程序PRG_inti,8800H後的數據全和87FFH裏的數據相同。
8000h~87ffh裏的程序是不是用來清除、擦除、燒寫FLASH用的?其只要打開CSS就存在。
答:SECTOINS段裏的load指出的是LOAD PROGRAM與FLASH燒寫時的共同地址。
因此若是LOAD PROGRAM時把load地址定到FLASH空間就會出現上面的錯誤。而FLASH燒寫固然就不會了。
因此LOAD PROGRAM與FLASH燒寫要寫不一樣的CMD文件。
SECTOINS段裏的run指出的是軟件調試運行時的地址,如:
MEMORY
{
PAGE 0: VECS: origin=0h, length=40h /*中斷向量表*/
FLASH: origin=100h, length=7000h /*;32Kflash*/
SARAM: origin=8000h, length=800h /*;當PON=1&&DON=0,*/
/*;SARAM映射爲程序存儲空間*/
PAGE 1: MMRS: origin=0h, length=60h /*;內部映射寄存器,或保留區間*/
B2: origin=60h, length=20h /*;32 WORDS DARAM*/
B0: origin=200h, length=100h /*;256 WORDS DARAM,CNF=0時*/
B1: origin=300h, length=100h /*;256 WORDS DARAM*/
}
SECTIONS
{
vectors: {} load=VECS, run=SARAM PAGE 0
.asminti: {} load=FLASH, run=SARAM PAGE 0/**/
.text: {} load=FLASH, run=SARAM PAGE 0
.data: {} >SARAM PAGE 0
.bss : {} >B2 PAGE 1
}
燒寫完FLASH後,復位,地址定位到0000H。單步執行,跳轉到主程序入口。.text段燒寫在100H地址處開始,但程序卻跳到了8043H處,這是關鍵字run映射的地址。把
vectors: {} load=VECS, run=SARAM PAGE 0
.asminti: {} load=FLASH, run=SARAM PAGE 0/**/
.text: {} load=FLASH, run=SARAM PAGE 0
改爲
vectors: {} load=VECS PAGE 0
.asminti: {} load=FLASH PAGE 0/**/
.text: {} load=FLASH PAGE 0
從0000H執行後就跳到了100H。
從中能夠看出run指定的只是軟件仿真時程序段的映射地址。