[英]Using `GCCs` pre-processor as an assembler
有各種各樣的開源匯編程序,例如gas , nasm和yasm 。 它們具有不同的pseudo-ops
和macro
語法。 對於許多開源項目,對匯編程序進行預處理以替換常量和平台條件。
假設您可以使用所有當前attributes
和#pragmas
,但不考慮翻譯性能(編譯/匯編為二進制時間), gcc
將對匯編程序產生哪些限制?
我不是在說內聯匯編 。
#define MOV(RA,RB) (OXFEB10000UL | RA << 16 | RB)
#define ADD(RA,RB) (OXFEB20000UL | RA << 16 | RB)
#define RET (OXFEB7ABCDUL)
unsigned long add4[] __attribute(section(".text")) =
{
ADD(R0,R1),
ADD(R2,R3),
MOV(R1,R2),
ADD(R0,R1),
RET()
};
我相信使用指針算法可以模擬.
等labels
。 也許這是一個XY問題 ; 我試圖理解為什么為什么有這么多的匯編器。 似乎所有事情都可以由預處理器完成,而匯編器實際上是程序員的偏愛。 或我缺少技術限制。
我想這可能與“您可以用匯編程序完成的事情,而不能用Shell代碼完成的事情”有關。
編輯:我已經將此從C重新標記為編譯器 。 我對匯編器的技術細節感興趣。 它僅僅是1-1
轉換並發出重定位(如編譯器那樣)還是更多? 我的意思不是讓人們像上面概述的那樣編寫匯編程序。 我試圖了解匯編程序在做什么。 我不相信有一本面向匯編程序的Dragon書籍 。 當然,預處理器本身不能創建binary
,而需要其他機器。 它僅翻譯文本。
gcc創建匯編程序會有哪些限制?
很多。 我們使用匯編程序進行匯編,使用C預處理程序進行預處理是有原因的。
首先,就像您自己展示的一樣,您不能使用常規的匯編語法,無論是Intel還是AT&T風格。 您必須使用那些難看的括號。
其次,您正在談論的__attribute__
指令與預處理器無關,它甚至無法識別它們。 它們是對編譯器的提示, 編譯器將依次生成由(或不由)這些屬性引導的匯編代碼。
也許這是一個XY問題
這是肯定的。
我試圖理解為什么為什么有這么多的匯編器。
出於同樣的原因,那里有各種各樣的編程語言,編譯器,汽車和衣服:一種工具不能滿足所有人的需求。 人們是不同的,他們使用工具鏈做不同的事情,他們發現一種工具比另一種工具更易於使用(就個人而言,如果它不需要AT&T語法(我只是不支持),我會使用GNU匯編器),等等
我認為XY問題描述不正確。 問題更多是“需要概念A來評估概念B ”。
概念A:什么是匯編器?
參見: David Solomon着的《 Assemblers and Loader》 。 [一些智慧的珍珠,一些古老的瑣事]
我很快發現該領域缺乏文學。 與存在大量文獻的編譯器形成鮮明對比的是,關於匯編器和裝載器的文獻很少。
匯編器包括:
匯編程序通常是1-1
轉換。 但是,通常會存在分支和調用的幾種變體。 通常被稱為長和短版。 使用的操作碼將取決於到目的地的距離 。 需要兩遍編譯器來優化前向分支。 由哈羅德暗示
概念B:使用“ C”預處理器作為匯編器。
“ C”預處理器可以模擬的最好的方法是1遍匯編器。 可以像這樣對大量的CPU /指令進行編碼。 盡管宏可能很麻煩。 沒有清單或外部參照 ,但大多數人不會錯過這些功能。 而且,由於預處理器的限制,語法將是奇怪的。 處理地址修復將很困難,因為標簽將通過使用指針來重用“ C”符號表,或者為標簽偏移量使用手工編碼的#define
。 這將這種方法限制為除基本塊之外的任何方法。
大型匯編程序例程(例如YUV / RGB轉換或MP3解碼)極不可能以這種方式使用。
多種架構代碼非常普遍。 例如,ARM wifi芯片可能會將其代碼作為固件嵌入到Linux內核中。 此技術可能在這里有用。 但是,對於不同的體系結構使用單獨的編譯器/匯編器,然后使用objcopy
嵌入它們,這更為理智。
這可能是最有用的。 實際上,許多工具(例如鏈接器和加載器)具有高級功能,可在運行時修補代碼。 它也可以用於在運行時有條件地更改例程。 函數指針幾乎一樣快捷且容易理解,更不用說緩存一致性問題了。
另請參閱: Ian Lance Taylor撰寫的 Gold Blog 。 [盡管他使用<templates>
]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.