簡體   English   中英

關於AT&T x86語法設計的問題

[英]Questions about AT&T x86 Syntax design

  1. 任何人都可以向我解釋為什么AT&T語法中的每個常量前面都有一個“$”?
  2. 為什么所有寄存器都有'%'?
  3. 這只是讓我做很多蹩腳打字的另一種嘗試嗎?
  4. 另外,我是唯一一個發現: 16(%esp)[esp+16]相比真的違反直覺嗎?
  5. 我知道它編譯成同樣的東西,但為什么有人想要輸入很多'$'和'%'而不需要? - 為什么GNU選擇此語法作為默認語法?
  6. 另一件事,為什么at&t語法中的每條指令前面都有一個:l? - 我知道它的操作數大小,但為什么不讓匯編程序弄清楚呢? (我是否想要在不是那么大的操作數上做一個movl?)
  7. 最后一件事:為什么mov參數倒置了?

是不是合乎邏輯:

eax = 5
mov eax, 5

at at&t是:

mov 5, eax
5 = a (? wait what ?)

注意:我不是想亂跑。 我只是不明白他們所做的設計選擇,我試圖了解他們為什么做了他們所做的。

1,2,3和5:符號有點多余,但我發現在匯編時發展是一件好事。 冗余有助於閱讀。 關於“讓匯編程序弄明白”的觀點很容易變成“讓讀取代碼的程序員把它弄清楚”,而當我是那個讀書的人時,我不喜歡它。 編程不是只寫任務; 甚至程序員自己也必須閱讀自己的代碼,語法冗余有很大幫助。

另一點是'%'和'$'意味着可以在不破壞向后兼容性的情況下添加新寄存器:添加時沒有問題,例如,一個名為xmm4的寄存器,因為它將寫為%xmm4 ,不能混淆使用一個名為xmm4的變量,它將被寫成沒有'%'。

至於打字的數量:通常,在組裝編程時,瓶頸是大腦,而不是手。 如果'$'和'%'減慢你的速度,那么要么你想要的速度比人們通常認為的那樣快,或者更可能的是,你手頭的任務太機械了,不應該用部件; 它應該留給自動代碼生成器,通俗地稱為“C編譯器”。

添加了'l'后綴來處理匯編程序“無法”弄明白的情況。 例如,這段代碼:

mov  [esp], 10

是不明確的,因為它不會告訴你是要寫一個值為10的字節,還是一個具有相同數值的32位字。 然后,英特爾語法要求:

mov  byte ptr [esp], 10

當你想到它時,這是非常難看的。 AT&T的員工想要做出更合理的事情,所以他們想出了:

movb   $10, (%esp)

他們喜歡系統化,並且到處都有'b'(或'l'或'w')后綴。 請注意,並不總是需要后綴。 例如,你可以寫:

mov   %al, (%ebx)

讓GNU匯編程序“弄清楚”,因為你在談論'%al',所以移動是針對單個字節的。 真的行 ! 然而,我仍然發現更好地指定大小(它確實有助於讀者,程序員本人是他自己的代碼的第一個也是最重要的讀者)。

對於“反轉”:反之亦然。 英特爾語法模仿C中發生的事情,其中​​值在右側計算,然后寫入左側的值。 因此,考慮到從左到右的閱讀,寫作在“反向”方向上從右到左。 AT&T語法恢復到“正常”方向。 至少他們考慮過這樣; 因為無論如何他們決定使用他們自己的語法,他們認為他們可以在他們認為的“正確的順序”中使用操作數。 這主要是一個慣例,但不是一個不合邏輯的慣例。 C約定模仿數學符號,除了數學是關於定義值(“讓x是值5”)而不是關於賦值 (“我們將值5 寫入稱為'x'的槽”)。 AT&T的選擇很有意義。 只有在將C代碼轉換為匯編時才會感到困惑,這個任務通常應留給C編譯器。

從歷史的角度來看,問題5的最后一部分很有意思。 用於x86的GNU工具遵循AT&T語法,因為當時他們試圖在Unix世界中占據一席之地(“GNU”意味着“GNU不是Unix”)並與Unix工具競爭; Unix在AT&T的控制之下。 這是在Linux甚至Windows 3.0之前; PC是16位系統。 Unix使用AT&T語法,因此GNU使用AT&T語法。

那么好的問題是:為什么AT&T發現自己發明自己的語法很聰明? 如上所述,他們有一些原因,這些原因並非沒有價值。 當然,使用自己的語法的成本是它限制了互操作性。 在那些日子里,C編譯器或匯編器作為一個單獨的工具沒有任何意義:在Unix系統中,它們應該由OS供應商提供。 此外,英特爾在Unix世界中並不是一個重要的參與者; 大系統主要使用VAX或Motorola 680x0衍生產品。 20年后,沒有人發現MS-Dos PC將成為台式機和服務器領域的主導架構。

1-2,5:他們可能選擇為寄存器加前綴,以便更容易解析; 你直接知道第一個字符是什么樣的標記。

4:不。

6:同樣,可能是為了讓解析器更容易找出要輸出的指令。

7:其實這更有意義的語法含義,移動什么地方 也許mov指令應該是ld指令。

不要誤會我的意思,我認為AT&T的語法很糟糕。

GNU匯編程序的AT&T語法可以追溯到Unix匯編程序1 ,它本身的輸入語法主要來自PDP-11 PAL-11匯編程序(約1970年)。

任何人都可以向我解釋為什么AT&T語法中的每個常量前面都有一個“$”?

它允許區分立即常量和內存地址。 英特爾語法以相反的方式實現,內存引用為[foo]

順便說一下,MASM(Microsoft匯編程序)不需要在語法級別上進行區分,因為它可以判斷操作數是符號常量還是標簽。 x86的其他匯編程序主動避免這樣的猜測,因為它們可能會讓讀者感到困惑,例如:IDEAL模式下的TASM(它在內存引用上發出警告而不是括號內),nasm,fasm。

PAL-11使用#作為立即尋址模式,其中操作數遵循指令。 沒有#的常量表示相對尋址模式,其中相對地址跟隨指令。

Unix使用與DEC匯編程序相同的語法來尋址模式,使用*代替@ ,而使用$代替# ,因為@#顯然不便於輸入2

為什么所有寄存器都有'%'?

在PAL-11中,寄存器定義為R0 =%0,R1 =%1,...,R6也稱為SP,R7也稱為PC。 DEC MACRO-11宏匯編程序允許將寄存器稱為%x ,其中x可以是任意表達式,例如%3+1表示%4

這只是讓我做很多蹩腳打字的另一種嘗試嗎?

不。

另外,我是唯一一個發現:16(%esp)與[esp + 16]相比真的違反直覺嗎?

這來自PDP-11 索引尋址模式,其中通過將寄存器的內容與指令之后的索引字相加來形成存儲器地址。

我知道它編譯成同樣的東西,但為什么有人想要輸入很多'$'和'%'而不需要? - 為什么GNU選擇此語法作為默認語法?

它來自PDP-11。

另一件事,為什么at&t語法中的每條指令前面都有一個:l? - 我知道它的操作數大小,但為什么不讓匯編程序弄清楚呢? (我是否想要在不是那么大的操作數上做一個movl?)

天然氣通常可以搞清楚。 其他裝配工在特定情況下也需要幫助。

PDP-11將b用於字節指令,例如: CLR vs CLRB 其他后綴出現在VAX-11中: l表示長, w表示字, f表示浮點數, d表示雙字, q表示四字,...

 Last thing: why are the mov arguments inverted? 

可以說,由於PDP-11早於英特爾微處理器,它就是另一種方式。


  1. 根據gas info-page,通過BSD 4.2匯編程序。
  2. Unix Assembler參考手冊§8.1 - Dennis M. Ritchie

與英特爾相比,AT&T語法顛倒操作數順序的原因很可能是因為最初開發Unix的PDP-11使用相同的操作數順序。

英特爾和DEC只是選擇相反的訂單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM