簡體   English   中英

將 [symbol + constant] Intel 語法尋址模式轉換為 AT&T 語法?

[英]Converting [symbol + constant] Intel syntax addressing mode to AT&T syntax?

我只是無法弄清楚如何在移動值時向目標添加偏移量,特別是在我擁有的英特爾語法中:

MOV   [gdtr + 2], EAX

對於 AT&T 語法,我嘗試將其轉換為:

movl %eax, gdtr(2,1)

junk '(2,1)' after expression時會出錯,但僅使用gdtr(,1)可以正常工作。

我不明白為什么我不能使用基本偏移,而只能使用比例因子。

簡單地寫

movl %eax, gdtr+2

基偏移尋址僅在偏移為寄存器時才有效。 使用尋址模式將兩個常量相加是沒有意義的。 其工作方式(無論語法如何)是匯編程序/linker 將symbol+constant解析為指令編碼的位移字段的單個數字。

就是gdtr+2

gdtr(2,1) [給出錯誤] 但僅使用gdtr(,1)工作正常。

AT&T 尋址模式中()括號內的內容只能是寄存器(和比例因子): disp(base, index, scale) 基數和索引是可選的,所以空是可以的,但無效(非注冊)不是。

當您指定一個沒有基數或索引的比例時,顯然您必須只使用一個逗號: (,,1)是關於空比例因子的錯誤。
您可以將其寫為gdtr+2(,1)以顯式不使用寄存器。

+2 是尋址模式中位移的一部分,而不是基址或索引寄存器,無論語法如何 請參閱有關 [base + index*scale + disp] 或 Intel 或 AMD 的有關尋址模式如何編碼的手冊的幾個問題 (就如何將其編碼為機器代碼而言,您正在做的是[disp32][disp16]尋址模式。)

正如 Nate 所指出的,linker 負責將匯編時文字常量 + 鏈接時常量符號地址轉換為機器代碼中的最終地址,編碼為disp32 (或disp16用於 16 位地址大小)。 或用於 x86-64 的 RIP 相對rel32

有趣的事實:一些 AT&T 匯編器接受(gdtr)作為gdtr的替代品,但不接受2(gdtr)


自己解決這個問題的方法:

通常,如果您卡在 NASM -> AT&T 上,您可以組裝 NASM 源代碼(例如nasm -felf )並使用 AT&T 反匯編程序(如objdump -drwC )進行反匯編。 但這對符號尋址模式語法沒有幫助,因為充其量objdump -dr只是用符號名稱信息注釋數字尋址模式。

因此,在這種情況下,您最好的選擇是讓 GCC 或 clang 發出使用符號名稱和數字常量的指令,如下所示

char gdtr[1024];                // global var so it has a symbol
char foo() { return gdtr[2]; }  // load from global symbol + constant.

在 Godbolt 編譯器資源管理器上使用gcc9.3 -O2 -m32編譯到這個 asm:

foo:
        movzbl  gdtr+2, %eax
        ret
gdtr:
        .zero   1024

有你的尋址模式,作為獎勵,帶有字節源的 movzx 的 AT&T 助記符。 當然,您可以擺弄類型。

編譯器是有用的資源; 在編譯簡單的 C 函數時,他們知道如何以“正常方式”做很多事情,並且他們知道調用約定和類型寬度。 包括 function 指針在內的所有內容的 AT&T 語法。 如果您遇到困難,請詢問編譯器 基本上,您唯一無法讓編譯器向您展示的是jmp far的語法(AT&T ljmp

暫無
暫無

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

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