什么是指針寄存器?
操作棧的寄存器
棧: 保存函數里面傳遞的參數,局部變量等。
EBP: 指向棧底的指針
ESP: 指向棧頂的指針。
計算入棧地址變化規則
通過OllDbg查看
有可能點擊安裝的時候棧區域第一次查看會沒有顯示上面的標題區域,可以通過右鍵點擊棧區域
選擇Appearanzhix選擇show bar 就有了,其他幾個區域一樣的。
現在我們嘗試通過F8執行一次push 命令來看棧頂指針寄存器的地址和數據變化。
首先我們需要通過F8執行讓CPU執行到push 命令處停下來,并記錄相關信息。 比如我這里。
(如果要和我一樣,先修改EAX 累加寄存器的值為 00000022,修改指令為push EAX,棧頂寄存器值可能不一樣。其實也沒必要,大家可以看自己的數據,按照下面的規則算就可以了)
執行推送前信息:
當前CUP位置是待執行的push 指令 :? push EAX;? 推送累加寄存器的值到棧頂。
當前 EAX 的值是:?00000022
當前ESP棧頂的地址是:??0199F7D4
當前ESP棧頂地址的對應的值是: 15F58E65
執行推送后,我們期望的信息:
當前 EAX 的值是:?00000022? 不變
當前ESP棧頂的地址是:??0199F7D0
當前ESP棧頂地址的對應的值是: 00000022
備注: 這里要說明下,為啥棧頂地址從0199F7D4變成了0199F7D0,這個是因為棧頂插入了4個字節,所以內存地址向高位偏移了4個字節。
我們嘗試執行下,看看數據是否是我們預期的。
最終確認,以上數據符合預期
練習題
我們上章節學習了 16位寄存器, 高八位寄存器,低八位寄存器。假如我們的指令是
push ax指令,那么數據又會怎么變化呢?? 這里我們嘗試一次。
先修改下數據,EAX 寄存器的值修改位 00001100
按F8執行語句,查看EAX的值,可以看到已經改變。
修改當前CPU執行位置的命令是: push ax
現在我們開始記錄執行后續命令前的數據:
當前CUP位置是待執行的push 指令 :? push ax;? 推送累加寄存器的值到棧頂。
當前 EAX 的值是:00001100
當前ESP棧頂的地址是:??0199FA78
當前ESP棧頂地址的對應的值是: 76987BA9
執行推送后,我們期望的信息:
當前 EAX 的值是:?00001100 不變
當前ESP棧頂的地址是:?0199FA76
當前ESP棧頂地址的對應的值是:7BA91100
F8執行語句后查看數據
執行后的結果:
當前 EAX 的值是:?00001100 不變
當前ESP棧頂的地址是:?0199FA76
當前ESP棧頂地址的對應的值是:7BA91100
以上為啥結果我會標記為紅色?
其實在這結果運行之前,我的預期運行結果是
當前 EAX 的值是:?00001100 不變
當前ESP棧頂的地址是:?0199FA76
當前ESP棧頂地址的對應的值是:76981100
為啥會犯這樣的錯誤?
先說結果我忽略了數據是小端數據存儲的。x86 架構采用小端字節序所以,其實我們通過OllDbg看到的數據并不是真實的內存展示的數據,也不是想當然的直接替換后面兩個字節的數據。
當然如果你對這以上沒有疑問,完全可以跳過后面的章節。接下來我會詳細描述下大小端的概念,以及為啥運行 push ax 后ESP棧頂的值是7BA91100,而不是76981100。
大端和小端?
比如有一個數據: 0x76 98 7B A9
在解釋大端和小端之前,我先說幾個概念。
低位字節,高位字節概念:
比如數據??0x76 98 7B A9
0x76 就是最高位字節,? 0xA9就是最低位字節。
高位字節 ---------------------------低位字節
0x76? ? ? ? ?0x98? ? ? ? ? ?0x7B? ? ? ? ? 0xA9
為了幫忙你記住,你就按照家里你的兄弟排位來,第一個生的就是老大,排位最高,后面依次老二,老三。
低地址,高地址概念:
就是內存地址序,比如運行指令之前ESP棧頂0x0199FA78
連續四個字節那么它們的地址就依次是
低地址---------------------------------------------------------高地址
0x0199FA78,0x0199FA79,0x0199FA7A,0x0199FA7B
以上概念清楚后,我們就來說說大端和小端的內存數據是如何存儲的。
大端:高位字節數據存入低地址,低位字節數據存入高地址。
小端:低位字節數據存入低地址,高位字節數據存入高地址。
基于X86架構平臺都是小端,無論是win,linux 還是其他系統。 有的設備平臺可能是大端。另外就是網絡通信中,基于TCP/IP標準,網絡字節序就是大端的。
有了上面概念后,就可以接受為什么我們執行push ax后結果為啥是7BA91100。
執行命令前,我們看看當時數據在內存中是怎么樣的。
執行命令 push ax; 將數據1100寫入ESP棧頂, ax 是十六進制,所以需要在0x0199FA78進制向左移動兩個字節。變成從0x0199FA76開始
以上就是內存存儲情況,將上面內存中的數據?OllDbg展示的數據就是 0x7BA91100。
如果有問題歡迎大家指出來,有疑問也可以一起討論。
上一篇:匯編學習之《數據寄存器》
下一篇:匯編學習之《變址寄存器》