簡體   English   中英

leaq的第一個操作數必須是一個內存地址,第二個操作數必須是一個寄存器嗎?

[英]Must the first operand of leaq be a memory address and the second operand be a register?

在ATT匯編語言中,當使用leaq指令時,其第一個操作數必須是內存地址,而不是寄存器或常量(前綴$ )嗎? 它的第二個操作數必須是一個寄存器嗎? 通過閱讀《計算機系統:程序員的觀點》,我得到了這種印象,並且從未見過與我的猜測不同的示例。 謝謝。

對,那是正確的。 從技術上講,可以對具有兩個寄存器操作數的lea進行編碼,但是這種編碼無效,並導致#UD異常。 請參見本參考這一個了解詳情。

即使它是可編碼的,您也永遠不會想要使用它。

如果要在寄存器中放入常量,則永遠不要使用lea mov $1234, %eaxlea 1234, %eax (disp32尋址模式下的絕對地址)更短,更高效。

LEA靜態地址的唯一用例是具有RIP相對尋址模式的64位代碼,例如lea symbol(%rip), %rax (7個字節),在mov $symbol, %eax (5個字節)的情況下無法使用,因為您需要與位置無關的代碼,並且/或者地址不適合32位零擴展立即數。

有關為何mov $symbol, %rdi不是最佳選擇的更多信息,請參見x86-64中的movq和movabsq之間的區別


在32位代碼lea symbol, %edi為6個字節(操作碼+ modrm + disp32),並且僅在Intel Sandybridge系列CPU上運行一個端口1或端口5。 https://agner.org/optimize/

mov $symbol, %edi是5個字節( 操作碼+ imm32簡短形式,無ModRM字節 ),並且可在任何ALU端口上運行。

對於16位代碼相同: mov $symbol, %di是3個字節,而lea symbol, %di是4個字節,具有相同的執行端口差異。 (或使用NASM語法,GAS .intel_syntax或MASM中的lea di, [symbol]mov di, symbolmov di, OFFSET symbol )。


不過,LEA在base = register尋址模式下很有用。 lea symbol(%rdi), %rax如果地址適合32位符號擴展的disp32 lea symbol(%rdi), %rax

或對於任意移位和加法用法,例如lea 123(%rdi, %rdi, 2), %eaxeax = 3*edi + 123 在不是地址/指針的值上使用LEA嗎?

暫無
暫無

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

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