進(jìn)制
進(jìn)制的本質(zhì)不是運(yùn)算蟀俊,而是對(duì)應(yīng)規(guī)則钦铺,俗稱查表。無論什么進(jìn)制肢预,都有自己的一套方法矛洞,然后,只要做出加法表烫映,乘法表沼本,便可以加減乘除。如果想像十進(jìn)制一樣熟練計(jì)算锭沟,那么直需要像上小學(xué)那樣背誦加法表和乘法表就可以了抽兆。
數(shù)據(jù)寬度/邏輯運(yùn)算
計(jì)算機(jī)中,任何存儲(chǔ)的數(shù)據(jù)都是有寬度的族淮,有長度限制辫红。如果超出界限,數(shù)據(jù)便會(huì)丟棄祝辣。
縮寫 | 中文 | 位數(shù) |
---|---|---|
BYTE | 字節(jié) | 8BIT |
WORD | 字 | 16BIT |
DWORD | 雙字節(jié) | 32BIT |
計(jì)算機(jī)CPU計(jì)算加法的方法是:先對(duì)兩個(gè)二進(jìn)制數(shù)X,Y進(jìn)行二進(jìn)制的xor異或運(yùn)算贴妻,用R存儲(chǔ)數(shù)據(jù);再進(jìn)行X,Y的and運(yùn)算并向左移一位蝙斜,用名惩。如果移位之后,不是為0孕荠,那么繼續(xù)運(yùn)算娩鹉。直到為0為止攻谁,那么異或的結(jié)果就是答案。
想測(cè)試自己是否真的理解底循,只需要計(jì)算2+3與2-3的結(jié)果是否正確即可巢株。
下面這幅圖除了主要用途不用背誦外,其他的都要背的滾瓜爛熟熙涤。之所以不需要背誦主要用途阁苞,是一因?yàn)檫@個(gè)主要用途是可以改變的。
需要熟練記住二進(jìn)制與十六進(jìn)制的對(duì)應(yīng)關(guān)系祠挫,方便理解計(jì)算機(jī)的無符號(hào)數(shù)與正數(shù)負(fù)數(shù)的關(guān)系那槽。
0x01 —— 0001 | 0x10 —— 0001 0000
0x02 —— 0010 | 0x11 —— 0001 0001
0x03 —— 0011 | 0x12 —— 0001 0010
0x04 —— 0100 | 0x13 —— 0001 0011
0x05 —— 0101 | 0x14 —— 0001 0100
0x06 —— 0110 | 0x15 —— 0001 0101
0x07 —— 0111 | 0x16 —— 0001 0110
0x08 —— 1000 | 0x17 —— 0001 0111
0x09 —— 1001 | 0x18 —— 0001 1000
0x0A —— 1010 | 0x19 —— 0001 1001
0x0B —— 1011 | 0x1A —— 0001 1010
0x0C —— 1100 | 0x1B —— 0001 1011
0x0D —— 1101 | 0x1C —— 0001 1100
0x0E —— 1110 | 0x1D —— 0001 1101
0x0F —— 1111 | 0x1E —— 0001 1110
| 0x1F —— 0001 1111
深刻理解下面這幅圖,就能理解計(jì)算機(jī)存儲(chǔ)正負(fù)數(shù)據(jù)的方式等舔。
匯編指令骚灸,用于修改寄存器以及其中的數(shù)據(jù)。
MOV EAX,0x45
MOV用來移動(dòng)數(shù)據(jù)到某個(gè)寄存器中慌植,這里的0x45位置屬于源甚牲,而EAX屬于目標(biāo)〉粒總的來說丈钙,就是將源中的這個(gè)0x45數(shù)據(jù)移動(dòng)到EAX寄存器中。
通用寄存器/內(nèi)存讀寫
下面的這個(gè)32位寄存器和16位寄存器以及8位的寄存器都需要按順序記住交汤。并且雏赦,要知道,不同位數(shù)的寄存器不是獨(dú)立的芙扎,32位里面包含16位星岗,16位里面又分高位,低位戒洼。
可以通過ollydbg形象的看到這樣的變化俏橘。不過,就是初次學(xué)習(xí)圈浇,容易將十六進(jìn)制和位數(shù)搞混敷矫。
就像杯子裝水的原理一樣,八位的寄存器里面最多填入兩個(gè)十六進(jìn)制的數(shù)汉额,但是也可以只填一個(gè)字符的十六進(jìn)制數(shù)曹仗,沒填滿默認(rèn)在前面補(bǔ)0
加法和減法的用法,和MOV類似蠕搜。但是怎茫,還是要記住,杯子裝水,寄存器內(nèi)的大小和操作的大小轨蛤。
MOV MAX,0x1 讓MAX寄存器中的值為1
ADD MAX,0x1 讓MAX寄存器中的值增加1蜜宪,并存入MAX寄存器中
SUB MAX,0x1 讓MAX寄存器中的值減1,并存入MAX寄存器中
如果結(jié)果為負(fù)數(shù)祥山,參考我理解的那個(gè)圓圃验。之前那個(gè)圓理解錯(cuò)了。實(shí)際上如果寄存器中存的是有符號(hào)的數(shù)字缝呕,那么那個(gè)圓兩邊的數(shù)除去符號(hào)后是軸對(duì)稱關(guān)系澳窑。
計(jì)算機(jī)是32位還是64位,是按寄存器的尋址地址來計(jì)算的供常,而不是說按寄存器的寬度進(jìn)行計(jì)算摊聋。
32位計(jì)算機(jī)之所以即使裝了8G內(nèi)存,還是只能識(shí)別出4G栈暇,那是因?yàn)?2為計(jì)算機(jī)中麻裁,內(nèi)存尋址最大也就是(0xFFFFFFFF+1)
而(0xFFFFFFFF+1)/1024得到的是kb(千字節(jié)),再除以1024得到M源祈,再除以1024得到G煎源,最后結(jié)果就是4G
需要注意的時(shí)候,計(jì)算除以1024前香缺,十六進(jìn)制要轉(zhuǎn)換成十進(jìn)制薪夕。
但是,如果說32位操作系統(tǒng)打了特定的補(bǔ)丁赫悄,那么就可能可以識(shí)別出8G內(nèi)存。正常情況下馏慨,32位操作系統(tǒng)只能識(shí)別4G內(nèi)存埂淮。
[0x123456] 內(nèi)存編號(hào)
0x123456 立即數(shù)
MOV WORD PTR DST:[0x12345678],0x1234
這里只能0x1234是因?yàn)楸硎鞠騼?nèi)存中寫16位立即數(shù),看前面word
同理写隶,也可以修改成BYTE倔撞,或者DWORD
內(nèi)存尋址/堆棧
學(xué)了一個(gè)新的匯編命令LEA
語法和MOV
類似,只不過慕趴,獲得的不在是寄存器中的值痪蝇,而是寄存器的地址。
LEA ESP,DWORD PTR DS:[0x0018FFFB]
將該32位(四個(gè)字節(jié))內(nèi)存地址存到ESP寄存器中
注意看下面這幅圖冕房,很容易理解錯(cuò)誤躏啰!這里L(fēng)EA執(zhí)行的命令是先獲得ECX的值,將這個(gè)值當(dāng)作地址來賦值給EAX耙册。
地址是可以計(jì)算的给僵,下面會(huì)有一些計(jì)算的語法
下面接觸到了堆棧的詳細(xì)概念蔓同,有那么一點(diǎn)不懂
想知道自己懂不懂,自己手動(dòng)實(shí)現(xiàn)一下堆棧蹲诀,去調(diào)試
PUSH EAX 在堆棧中壓入新的值斑粱,值是EAX寄存器中的值,并且棧頂向上移動(dòng)脯爪,即ESP-4
POP EAX 將棧頂所指的地址的值存到EAX中则北,然后棧頂向下移動(dòng)
PUSHAD 將8個(gè)通用寄存器中的值全都存到堆棧中
POPAD 將堆棧中存的8個(gè)通用寄存器的值都返回到那8個(gè)寄存器中
上面這樣做的好處是,假設(shè)一開始不需要用到8個(gè)32位通用寄存器的值披粟,但是后期可能會(huì)用到咒锻,那么就先存到堆棧中,然后就可以對(duì)8個(gè)通用寄存器為所欲為守屉,為所欲為完了之后惑艇,再POPAD指令,那么那8個(gè)寄存器就又恢復(fù)到PUSHAD到堆棧中的樣子了
EFLAGS寄存器
標(biāo)記藍(lán)色的位都是無法控制的拇泛。需要記住的是CF/PF/AF/ZF/SF/OF這幾個(gè)位
上面叫做標(biāo)志寄存器滨巴,需要注意的是,下面關(guān)于標(biāo)志寄存器的每個(gè)操作俺叭,都要注意數(shù)據(jù)寬度!
CF 只有運(yùn)算結(jié)果最高位產(chǎn)生了一個(gè)進(jìn)位或借位熄守,CF的值才為1蜈垮,否則為0。
注意:最高位是由數(shù)據(jù)寬度決定的裕照!
PF 奇偶標(biāo)志攒发,用來判斷運(yùn)算結(jié)果中‘1’的個(gè)數(shù)的奇偶性,‘1’的個(gè)數(shù)為偶數(shù)晋南,那么PF位為1
(但是惠猿!PF判斷依據(jù)只是最低有效字節(jié),即只是根據(jù)最后八位來判斷负间,如果用ax寄存器而不是al/ah偶妖,會(huì)發(fā)現(xiàn)有時(shí)候即便是偶數(shù),可是PF還是為0)
注意:這里判斷的1是二進(jìn)制情況下的判斷
AF 輔助進(jìn)位標(biāo)志政溃。假設(shè)數(shù)據(jù)寬度為8位趾访,那么第四位進(jìn)位,AF就為1
注意:AF是否為1董虱,看得是數(shù)據(jù)寬度一半的那個(gè)值是否要進(jìn)位
注意看下圖的箭頭處腹缩,EFL的值實(shí)際上就是上面要背誦的那幅圖的16進(jìn)制寫法,將202轉(zhuǎn)成二進(jìn)制后,對(duì)應(yīng)上面那幅圖就是:
0010 0000 0010
之所以要會(huì)拆位藏鹊,是因?yàn)橛械牡胤經(jīng)]有ollydgb那樣C\P\A等等這樣拆開的润讥,是直接用EFL表示,所以要會(huì)自己拆盘寡。
XOR EAX,EAX 利用異或運(yùn)算把EAX清零
ZF 零標(biāo)志ZF楚殿,如果運(yùn)算結(jié)果位數(shù)全為0,則ZF為1竿痰,否則ZF為0
SF 與運(yùn)算結(jié)果的最高位相同(二進(jìn)制)
OF 溢出標(biāo)志符脆粥,有符號(hào)計(jì)算看OF,無符號(hào)計(jì)算看CF
先看數(shù)據(jù)寬度影涉,如果無符號(hào)運(yùn)算变隔,那么看計(jì)算結(jié)果有沒有超出數(shù)據(jù)寬度,如果是有符號(hào)計(jì)算蟹倾,那么看計(jì)算結(jié)果有沒有超過數(shù)據(jù)寬度一半匣缘,超過了就說明溢出來。
上面是否溢出鲜棠,可以參考那個(gè)圓肌厨,要深刻理解那個(gè)圓,就知道計(jì)算結(jié)果是否溢出豁陆。
ADC帶移位的加法柑爸,所謂帶移位的加法,就是在執(zhí)行這個(gè)指令之前盒音,手動(dòng)將CF位設(shè)置為1表鳍,然后在運(yùn)算的時(shí)候,帶上CF的進(jìn)位去做運(yùn)算祥诽。最后譬圣,將運(yùn)算之后的結(jié)果存到ADC指令的第一個(gè)參數(shù)里。
同理原押,SBB帶借位的減法,運(yùn)算后也會(huì)存到SBB的第一個(gè)參數(shù)中偎血。
上面的計(jì)算操作诸衔,前提都是先將CF位變成了1
XCHG是交換指令,將兩個(gè)參數(shù)的內(nèi)部的值進(jìn)行交換颇玷。
例如:XCHG AL,CL
下面這個(gè)指令有點(diǎn)特殊笨农,移動(dòng)的兩個(gè)目標(biāo)的數(shù)據(jù)寬度必須一致
實(shí)際上這個(gè)參數(shù)就是將兩個(gè)通用寄存器中存儲(chǔ)的地址,全都向一個(gè)方向進(jìn)行4/2/1的移位帖渠,若DF位為0谒亦,則代表向堆棧下方移位,若DF為1則代表向堆棧上方移位。而堆棧是越向下份招,內(nèi)存地址越大切揭。
而MOVS操作的EDI,ESI,存儲(chǔ)的都是堆棧中的地址編號(hào)
STOS這個(gè)指令就是將EAX中的值廓旬,存儲(chǔ)到EDI寄存器中的那個(gè)地址中去,之后再將EDI中存儲(chǔ)的值進(jìn)行移位谐腰,移位多少孕豹,看存多大的數(shù)據(jù)。存多大的數(shù)據(jù)十气,看用的是STOSB/STOSW/STOSD哪一個(gè)励背。至于移位的方向,看DF的值為1還是0
JCC
jmp 寄存器/立即數(shù)
修改EIP的值為jmp后的參數(shù)砸西,讓cpu執(zhí)行相關(guān)地址的匯編指令
call 寄存器/立即數(shù)
call使用的時(shí)候叶眉,需要將call跳轉(zhuǎn)的那個(gè)地址打斷點(diǎn)
retn 回到call指令存在的那個(gè)地址的下一個(gè)地址,retn的本質(zhì)就是POP EIP
jmp是直接跳籍胯,只修改EIP的值竟闪,而call配合retn還會(huì)回到call指令的下一個(gè)地址。call感覺是調(diào)用某個(gè)函數(shù)杖狼,調(diào)用完了之后炼蛤,還會(huì)回到程序執(zhí)行的下面流程。而EIP的值蝶涩,不能用mov修改理朋。
根據(jù)自己嘗試發(fā)現(xiàn),當(dāng)執(zhí)行 cmp 操作數(shù)1绿聘,操作數(shù)2
的時(shí)候嗽上,若操作數(shù)1大于操作數(shù)2,那么ZF位為0熄攘,SF位也為0兽愤;當(dāng)操作數(shù)1小于操作數(shù)2的時(shí)候,那么ZF為0挪圾,SF為1浅萧;當(dāng)操作數(shù)1等于操作數(shù)2的時(shí)候,ZF位為1哲思,SF為0洼畅。
總的來說,cmp指令真的就像是在做sub減法一樣棚赔,只不過沒有將結(jié)果存到操作數(shù)1中
TEST指令就是用來判斷某個(gè)寄存器中的值是否為空帝簇,因?yàn)門EST用的是與運(yùn)算徘郭,只有當(dāng)同一個(gè)寄存器中,值為0的時(shí)候丧肴,與出來的結(jié)果才為0残揉,ZF位才為0
TEST 寄存器1,寄存器1
下面的內(nèi)容需要熟記闪湾,推導(dǎo)比較麻煩冲甘,所以目前先都記住。
JE/JZ 結(jié)果相等時(shí)跳轉(zhuǎn)/結(jié)果為0時(shí)跳轉(zhuǎn) ZF=1
這兩個(gè)指令本質(zhì)上是相同的途样,都是看ZF位的值江醇,來決定是否跳轉(zhuǎn)
JNE/JNZ 結(jié)果不相等時(shí)跳轉(zhuǎn)/結(jié)果不為0時(shí)跳轉(zhuǎn) ZF=0
這兩個(gè)指令就是和上面正好相反
堆棧圖
call執(zhí)行完后,向堆棧中壓入的值何暇,叫做函數(shù)的返回地址
堆棧平衡指的是使用完一個(gè)堆棧后陶夜,堆棧和原來的堆棧沒區(qū)別。
堆棧圖個(gè)人感覺自己能根據(jù)匯編指令畫出來了裆站。但是不知道是不是真的懂了条辟。。宏胯。以后如果不懂的話羽嫡,那么這里還需要再畫一遍。
實(shí)際上肩袍,只要前面的指令記得滾瓜爛熟杭棵,那么堆棧圖這里就不是問題。
按F8和F7的區(qū)別就在于氛赐,F(xiàn)8是一條一條的指令執(zhí)行魂爪,而F7則是會(huì)跟著函數(shù)去執(zhí)行
匯編部分終于結(jié)束了。JCC的指令還需要查表艰管,其他的得多復(fù)習(xí)滓侍,堆棧是重點(diǎn)。