我最近在為基于 Motorola 68000 的系統(SEGA Mega Drive)鏈接多個目標檔案時遇到了一個小問題。問題是,當一個目標檔案的輸入段結束而下一個開始時,聯結器用零填充記憶體地址,以便下一個目標檔案開始在四位元組邊界上對齊。下面的文本是聯結器輸出的記憶體映射。如您所見,.text 輸出部分包含三個目標檔案。前兩個(main.o、swap.o)是用 C 語言撰寫的,使用m68k-elf-gcc編譯和組裝。第三個(swap_asm.o)是用68000匯編手寫的,使用vasm組裝. swap.o 開頭的函式通常從地址 0x0000001E 開始。但是,聯結器用兩個位元組*填充*swap.o檔案的開頭,特別是0x0000。所以,swap.o 從 0x00000020 開始。但是,swap_asm.o 沒有對齊,而是從一個非四位元組對齊的地址 0x00000036 開始。有沒有辦法讓聯結器不添加任何填充并立即啟動 swap.o?我知道有一些解決方法,比如用 NOP 填充空間,但我想知道是否有辦法不做 *fill*?
.text 0x00000000 0x4c
main.o(.text)
.text 0x00000000 0x1e main.o
0x00000000 main
swap.o(.text)
*fill* 0x0000001e 0x2
.text 0x00000020 0x16 swap.o
0x00000020 swap
swap_asm.o(.text)
.text 0x00000036 0x16 swap_asm.o
0x00000036 swap_asm
uj5u.com熱心網友回復:
68000 處理器需要對齊指令(這個要求也適用于資料)。盡管有 CPU 要求(不可跳過),聯結器還使用一個腳本,其中段需要有一些對齊(通常是為了滿足這個 cpu 要求)
雖然聯結器腳本可以調整,但更改對齊方式可能會使聯結器產生不正確的代碼(因為上一段中所說的),但無論如何,這是您可以嘗試和測驗的東西。
摩托羅拉 68000(以及更多的 16 位版本的 MegaDrive)在奇數地址上請求 16 位傳輸時觸發總線錯誤陷阱。如果是 32 位,也會發生同樣的情況(但這也發生在 68030 之前,我認為 68040 已經處理了這個問題,例如英特爾處理器)
uj5u.com熱心網友回復:
所以我找到了我的答案。當匯編器檢測到匯編檔案中正在處理長(32 位)資料時,它會自動將輸入部分沿 4 位元組邊界對齊。您實際上可以在鏈接描述檔案中使用 SUBALIGN 覆寫它。這是我的聯結器腳本,將輸入部分沿 2 位元組邊界對齊。
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x00400000
}
SECTIONS
{
.text : SUBALIGN(0x2) {
*(.header)
*(.boot)
obj/main.o(.text)
*(.text)
*(.isr)
*(.vdp)
} > rom
.data : { *(.data) } > rom
.bss : { *(.bss) } > rom
}
新的聯結器映射:
.text 0x00000000 0x4a
main.o(.text)
.text 0x00000000 0x1e main.o
0x00000000 main
swap.o(.text)
.text 0x0000001e 0x14 swap.o
0x0000001e swap
swap_asm.o(.text)
.text 0x00000034 0x16 swap_asm.o
0x00000034 swap_asm
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/415422.html
標籤:
上一篇:如何在匯編x86中使用變數
