匯編語言理解指針(指針就是匯編的間接尋址,其實就是一個簡單方便的運算指令,計算完畢直接就賦值,不是從內存中去取值后賦值)


有空自己也寫一個學習筆記,先把參考文章記下了:

http://www.cnblogs.com/aguncn/archive/2012/11/14/2769989.html
http://www.cnblogs.com/aguncn/archive/2012/11/14/2769814.html

http://segmentfault.com/q/1010000000627497

http://blog.csdn.net/herecles/article/details/6080226

我的理解:指針就是使用mov方法的間接尋址。想要明白指針,必須懂得LEA和MOV指令的區別。然后就覺得已經豁然開朗。

mov 和 lea 的區別

mov ecx,[eax+0x30]表示先運算eax+0x30得到一個結果,以這個結果為地址找一個ecx長度的內存數賦給ecx
lea ecx,[eax+0x30]表示先運算eax+0x30得到一個結果,把這個結果(mov時地址)賦給ecx
效果為ecx=eax+0x30 (這里eax參與了運算卻沒有改變值)
dword 雙字 就是四個字節
ptr pointer縮寫 即指針
[]里的數據是一個地址值,這個地址指向一個雙字型數據
比如mov eax, dword ptr [12345678] 把內存地址12345678中的雙字型(32位)數據賦給eax

----------------------------------------------------
MOV與LEA的區別
可以說,mov 這個匯編指令在 匯編語言程序中是 非常 非常常見的一個指令. 打個最簡單的比方,就好比我
們人要每天 說話一樣..在匯編語言中,Mov 指令就好比 我們人要每天說話一樣。 每一個程序都離不開 Mov
指令。
Mov指令:
傳送指令,可以用於傳送寄存器,也可以用於傳送內存地址.
lea指令:
傳送指令。

如果是剛剛學習 匯編語言的朋友,看到上面的解釋一定會很疑惑,Mov 和 Lea都是傳送指令,那么它們直
接的區別在哪里?
下面詳細 解釋 Mov 與Lea 匯編指令的區別.
先作舉一個生活中的例子, 比如你要坐車去電影院,你可以告訴司機電影院的地址,然后司機根據地址將你送
到電影院. 你還可以,告訴司機電影院的名字,司機通過名字 將你送到電影院. 我們用這兩種方式都可以 順
利的到達 自己想到底的電影院.
Mov 和lea 的作用就是像上面例子說的一樣.用不同的方式(傳送方式),達到同一個目的(傳送數據).換句話
說,Mov 指令傳送方式,是將存放內存數據的地址進行傳送. 而Lea則是恰恰相反,Lea是直接將內存數據進行傳
遞.
下面用一個例子說明 lea與mov 的區別:
mov ecx,30
add ecx,eax
----------------------------------------------------
lea ecx,[eax+30]
----------------------------------------------------
mov ecx,[eax+30]表示先運算eax+30得到一個結果,以這個結果為地址傳遞到一個ecx長度的內存地址存放ecx
lea ecx,[eax+30]表示先運算eax+30得到一個結果,把這個結果傳遞到ecx中。相當於ecx=eax+30

希望這篇文章 能夠幫助正在 為mov 和lea區別而煩惱的朋友們. 這篇文章花費 2個晚上,完成排版,整理。

1 . MOV 的右值必須是常量,而不能是表達式,比如 可以寫MOV EAX, EBP,但不能寫MOV EAX, EBP + 8
這是因為EBP + 8本身也需要一條指令來計算,所以不能跟MOV寫在一條指令里。

2 . 注意到在匯編指令的內存地址符 [ ] 內可以做算術運算,那是因為內存地址的計算在CPU里是由專門的處理單元AGU來處理的,並不占用算術運算單元ALU的時鍾周期。但如果用MOV 接內存地址符號[]的話,會把[]里的地址指向的內存的內容取出來放入寄存器。 比如 mov eax,[ebx+ecx*4h-20h],會把ebx+ecx*4h-20h計算的結果當成一個內存地址,然后去內存把該地址的內容取出送往eax。

3 . 如果我們只是想得到算術運算結果怎么辦呢?這時候就可以用到LEA指令了。因為LEA后面接內存地址符[]會把地址,而不是地址里的內容送入寄存器。比如,我們想計算ebx+ecx*4h-20h的結果,就可以這樣寫: lea eax,[ebx+ecx*4h-20h]。當然如果不用lea指令也可以達到目的,不過那樣寫起來就麻煩多了: imul ecx, 4 add ebx, ecx sub ebx, 20h mov eax, ebx

----------------------------------------------------

死記硬背:

#include "stdafx.h"
#include <iostream>

using namespace std; 

void myfun()
{
    int num = 5;
    int *ptr = &num;
    std::cout << *ptr << std::endl;
}

int main(){
    myfun();
    return 0;
}

對應的匯編(VC6):

void myfun()
13:   {
00401780   push        ebp
00401781   mov         ebp,esp
00401783   sub         esp,48h
00401786   push        ebx
00401787   push        esi
00401788   push        edi
00401789   lea         edi,[ebp-48h]
0040178C   mov         ecx,12h
00401791   mov         eax,0CCCCCCCCh
00401796   rep stos    dword ptr [edi]
14:       int num = 5;
00401798   mov dword ptr [ebp-4],5 // 把5放到ebp-4這個地址的內存中去
15:       int *ptr = &num;
0040179F   lea eax,[ebp-4] // 計算ebp-4的值,並把這個地址值放到eax里,就這么簡單! 004017A2   mov dword ptr [ebp-8],eax // 給ptr分配了一塊內存(大小為4,地址是ebp-8),並把eax里的值放作為內容,放到這個新分配的內存里。 16:       std::cout << *ptr << std::endl;
004017A5   push        offset @ILT+200(std::endl) (004010cd)
004017AA   mov         ecx,dword ptr [ebp-8]
004017AD   mov         edx,dword ptr [ecx]
004017AF   push        edx
004017B0   mov         ecx,offset std::cout (0047c0c0)
004017B5   call        @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
004017BA   mov         ecx,eax
004017BC   call        @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
17:   }
004017C1   pop         edi
004017C2   pop         esi
004017C3   pop         ebx
004017C4   add         esp,48h
004017C7   cmp         ebp,esp
004017C9   call        __chkesp (00406830)
004017CE   mov         esp,ebp
004017D0   pop         ebp
004017D1   ret

 lea的英文解釋是: Load Effective Address. 這個有效地址是指,四則運算后得到有效地址,然后就賦值,並不是從某個有效地址里去取數據。

 -------------------------------------------------------

下一句是pointer = &count;,將pointer指向count的內存地址,我們看對應的匯編代碼:

代碼:
lea         eax,[ebp-4]
mov         dword ptr [ebp-0Ch],eax

前面說過,ebp-4是count變量的內存地址,為了直觀點,我把上面的匯編代碼改一下:

代碼:
lea         eax,[count]
mov         dword ptr [pointer],eax

lea指令就是把一個內存變量有效的地址傳送給指定的寄存器。第一句lea   eax,[ebp-4]是把count的地址傳到eax寄存器,根據剛才在Watch窗口中看到的count地址是0012ff7c,那么eax里面的值就是0012ff7c。第二句mov   dword ptr [ebp-0Ch],eax是把eax中的值傳到ebp-0Ch(pointer)中。很明顯,pointer = &count;這句代碼就等同於pointer = 0012ff7c;。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM