最近在看linux-0.11核心,看到lea這個指令,google搜尋了一下,轉給大家,一起學習@!
先看這個這個文法格式吧:
對AT&T來說,定址方式比較怪異,但又非常簡潔,文法格式如下:
segreg:base_address(offset_address, index, size) ;例子movl %eax, label1(, $2, $4)movl %ebx, (label2, $2,)movl %ecx, (%esp)
其效果為 segreg:base_address + offset_address + index * size
segreg為分段模式下段寄存器,base_address為基址,offset_address 為位移,index * size決定了第幾個元素,其中size為元素長度,只能為1,2,4,8等等,這些元素都是可選的,index預設為0,size預設為1。
常見1:
http://www.adam8157.info/blog/2011/01/interesting-opcode-lea/原文:
最近惡補彙編時發現lea指令很有意思, 但大部分書都把它一筆帶過, 同時網上的資料又很少, 所以記一下.
lea, load effective address, 載入有效地址. 指令形式是從儲存空間讀資料到寄存器, 效果是將儲存空間的有效地址寫入到目的運算元, 簡單說, 就是C語言中的”&”.
例如在32位環境下, 有記憶體位置標籤foo, 則下面兩行效果相同:
movl $foo, %edileal foo, %edi
同時, lea還有個很有用但同時又很難理解的用法, 例如這樣:
leal 5(%edx, %edx, 2), %eax
假設%edx的值為x, 上面這行會將%eax的值設定為”3x+5″.
奇怪吧, 一個取址的指令怎麼用來做簡單算術操作了? 其實理解起來也不難, 5(%edx, %edx, 2)是儲存空間”3x+5″這個地址中的值, 這個值作為leal的源運算元會被取地址, 地址是什麼? 自然就是”3x+5″!
值得注意的是, 不管是AT&T還是Intel文法, lea都是載入有效地址, 所以運算結果需得在地址空間能表示的大小範圍內.
PS: 可能有人會問為什麼不把源運算元寫成5(, %edx, 3), 這個嘛, 因為這種定址模式的比例因素只能是1, 2, 4或者8.
常見2:
定址方式:
0x4(%esp)的操作是把寄存器esp中的值取出,然後加上4,得到的值作為地址,間接定址得到需要的資料
例如:
pushl -0x4(%ecx)
該指令的含義是取出寄存器ecx的值,減去4,將得到的值作為地址,在記憶體找到該地址對應的值,將其壓入棧中。
這是執行後的結果:
ecx 0xbff01450
esp 0xbff0143c 0xbff0143c
ebp 0xbff01498 0xbff01498
(gdb) x/x $esp
0xbff0143c: 0x0804840a
(gdb) x/x 0xbff0144c
0xbff0144c: 0x0804840a
其中,記憶體0xbff0144c即為%ecx-4後得到的值
指令LEA的作用和80x86彙編有些類似,即地址傳遞,下面舉例說明:
LEA 0x4(%esp), %ecx
該指令的作用是,取出esp寄存器裡的值,加上4,不再繼續定址,而是將得到值直接傳遞給ecx;如果是其他指令,則還需進行間接定址,再傳值。