2017-06-15 136 views
3

什麼時候在x86中使用大小指令似乎有點含糊。 This x86 assembly guide說以下內容:什麼時候應該在x86中使用尺寸指令?

通常,的數據項中的一個給定的存儲器地址 預期的大小可以從彙編代碼指令,其中它是 引用來推斷。例如,在所有上述指令中,可以根據寄存器 操作數的大小來推斷存儲器區域的大小。當我們加載一個32位寄存器時,彙編器可能會推斷我們所指的內存區域是4個字節寬。 當我們將一個字節寄存器的值存儲到存儲器時,彙編器可能會推斷出我們希望地址引用內存中的單個字節 。

他們給出的例子非常微不足道,比如將立即值移入寄存器。
但是關於更復雜的情況,如下列內容:

mov QWORD PTR [rip+0x21b520], 0x1 

在這種情況下,是不QWORD PTR大小指令多餘的,因爲,按照上面的指導,我們可以假設,我們要由於RIP爲8字節,因此將8個字節移入目標寄存器? x86架構上尺寸指令的權威規則是什麼?我無法在任何地方找到答案,謝謝。

更新:正如Ross指出的那樣,上例中的目的地不是寄存器。以下是一個相關的例子:

mov esi, DWORD PTR [rax*4+0x419260] 

在這種情況下,不能把它假設我們要移動4個字節,因爲ESI爲4個字節,使得DWORD PTR指令冗餘?

+2

RIP不是目標寄存器。目的地根本不是寄存器,它是一個內存位置。該指令將值1存儲在內存中的地址「RIP + 0x21b520」。 –

+0

@RossRidge啊,我從來沒有這樣看過。謝謝,這爲我澄清了一點,但我已經看到了目的地其實是寄存器的其他情況。我會更新這個問題。 – Hello

+1

你的第二個例子中不需要'dword ptr'。 – interjay

回答

-1

它變得更糟,彙編語言是由彙編程序定義的,該程序讀取/解釋/解析它。特別是x86,但是作爲一般規則,任何兩個彙編程序沒有技術上的理由使得相同的目標程序具有相同的彙編語言,它們往往是相似的,但不一定非要。

你陷入了幾個陷阱,首先關於你正在使用的彙編程序使用的特定語法關於size指令,然後第二,是否有默認值。我的建議總是使用size指令(或者如果有獨特的指令助記符),那麼你不必擔心它是正確的嗎?

+0

我通常會做相反的事情:我最初從不使用任何,只有在彙編程序抱怨時才添加它們。如果找不到,每個彙編程序都會報錯。特別是在我使用最多的彙編程序(Delphi的BASM)中,變量和結構成員具有指定的大小,所以很少有必要。使編寫代碼更容易,IMO。我使用過NASM,FASM,YASM,BASM,TASM,MASM,如果有必要,他們都會抱怨。 –

+0

我想我聽說過一些有缺省操作數大小的令人討厭的x86彙編程序。也許是內置於emu8086的? –

1

RIP或地址中的任何其他寄存器只與尋址模式有關,而不是數據傳輸的寬度。內存引用[rip+0x21b520]可以使用1,2,4或8字節訪問,常數值0x01也可以是1到8個字節(0x010x00000001等相同)。因此在這種情況下,操作數大小必須明確提及。

與寄存器爲源或目的地,操作數大小是隱式的:如果,比如說,EAX被使用時,數據是32位或4個字節:

mov [rip+0x21b520],eax 

當然,在非常漂亮的AT語法,操作數大小被標記爲指令助記符的後綴(l這裏)。

movl $1, 0x21b520(%rip) 
+0

謝謝!我用一個更好的例子更新了這個問題,我用gdb調試二進制文件時發現了這個例子。在這種情況下,尺寸指令似乎是多餘的,不是嗎? – Hello

+0

@old_timer,嗯,什麼是? – ilkkachu

+1

@ilkkachu:可怕,是的,但美麗? Naaaah。 –

3

你是對的;這是相當模糊的。假設我們談論的是英特爾語法,確實如此,您可以使用大小指令來避開而不是。任何時候彙編器都可以自動計算出來,它們是可選的。例如,在指令

mov esi, DWORD PTR [rax*4+0x419260] 

的DWORD PTR符是可選的確切原因,你想:彙編能弄清楚,它是將一個DWORD大小的值,因爲該值被移入DWORD大小的寄存器。

類似地,在

mov rsi, QWORD PTR [rax*4+0x419260] 

的QWORD PTR說明符是可選的確切相同的原因。

但它並不總是可選的。考慮你的第一個例子:

mov QWORD PTR [rip+0x21b520], 0x1 

這裏,QWORD PTR說明符可選。如果沒有它,彙編程序不知道您想要從地址rip+0x21b520開始存儲什麼大小的值。 0x1應該作爲BYTE存儲嗎?擴展爲WORD?一個DWORD? QWORD?有些彙編器可能會猜測,但是如果沒有明確指定你想要的結果,你不能確定正確的結果。

換句話說,當值在寄存器操作數中時,大小說明符是可選的,因爲彙編程序可以根據寄存器的大小計算出大小。但是,如果處理立即值或內存操作數,則可能需要使用大小說明符來確保獲得所需的結果。

個人而言,我更喜歡總是包括我寫代碼時的大小。這是一些更多打字的角色,但它迫使我考慮它並明確說明我想要的。如果我搞砸了,編寫了一個不匹配的代碼,那麼彙編程序會對我大聲尖叫,這已經不止一次地發現了錯誤。我也認爲在那裏增強可讀性。所以在這裏我同意old_timer,雖然他的觀點似乎有些不受歡迎。

反彙編器在其輸出中也往往是冗長的,包括大小說明符,即使它們是可選的。 Hans Passant在評論中提出理論,這是爲了保持與老派裝配工的向後兼容性,這些總是需要這些,但我不確定這是否屬實。它可能是其中的一部分,但根據我的經驗,反彙編程序往往在不同的方式下很難做出很多,我認爲這只是爲了更容易分析您不熟悉的代碼。

請注意,AT & T語法使用略有不同的機智。它不是將大小作爲操作數的前綴,而是將其後綴添加到指令助記符中:字節爲b,字爲w,雙字爲l,雙字爲q。所以,前三次的例子變成:

movl 0x419260(,%rax,4), %esi 
movq 0x419260(,%rax,4), %rsi 
movq $0x1, 0x21b520(%rip) 

此外,前兩個指示,lq前綴是可選的,因爲彙編器可以推斷出合適的大小。在最後一條指令中,就像在英特爾語法中一樣,前綴是非可選的。因此,與英特爾語法一樣,ATT語法也是如此,只是大小說明符的不同格式。

+0

一些彙編程序,如MASM或TASM或Delphi的內置彙編程序,可以聲明變量或結構成員具有一定的大小。在這些彙編程序中,使用這些變量作爲目標或源操作數也使得不需要使用顯式大小指令。我不會稱這種模糊的,只是,好的,有時難以閱讀。 –

+0

是的,高級語言風格的彙編器使其變得更加複雜。我考慮過提及這一點,但決定的答案不再需要。 :-)它遵循相同的一般原則,即如果彙編程序可以推斷大小,則不需要明確指定它。但是隻有類型感知的彙編器才能進行這些推導,而且這些並不是經常用於我的經驗。 –

+0

我最常用的是一個真正的(內置)彙編程序,但是結構和變量是用語言(Object Pascal)定義的。這使得事情變得非常簡單,並且比外部彙編器更好用(我也這麼做了,只是爲了好玩)。事實上,如果彙編程序可以推導出大小,則不需要使用指令。我通常不使用任何,只有在彙編程序抱怨時才添加它們。 –

相關問題