本來今天計劃學習《PE》的第二章,可是卻發現戚利老師寫了3個PE程序自己看不懂,查了些資料才知道是Win32彙編編程,於是又找來《Windows環境下32位彙編語言程序設計(第2版)》(羅雲彬)學習,今天學習了前兩章和第三章的一部分,現在把筆記貼下來,其實也不是爲了交流,就是想記錄一下……
第一章介紹了Intel86系列處理器的發展歷程和Windows操作系統的發展歷程
第二章介紹了Win32彙編的開發環境
第三章介紹了Win32彙編的語法
1.1.1.1
8086,16位,1M尋址(20根地址線)
80386,32爲,4G尋址(32根地址線),多任務,保護模式
80486,倍頻技術
80586,Pentium(其他公司把intel兼容產品叫x86),超標量體系結構
P6,多方面性能提升
PMMX,增加了多媒體技術
PⅡ
PⅢ
P4,主頻到1.4GHz,2000年
1.1.1.2
CISC:複雜指令系統,指令不等長,指令多
RISC:精簡指令系統,等長,指令少
86系列CPU受軟件限制,很多老舊東西都沒改
1.1.2
93年,WindowsNT(NT=new technology),32位系統
95年,Windows95,實現即插即用功能
2000年,Windows2000,Win9x系列和WinNT系列統一爲後者
1.1.3
wintel聯盟,微軟和英特爾”最佳拍檔“
1.2
Windows的特點,多任務,內存管理,函數調用,設備無關等
1.3.1
實模式:加速版8086,1M尋址,可進入保護模式,32位寄存器可用,新增兩個段寄存器不必考慮重裝問題,新指令,拿到8086機子上不能使用
保護模式:4G尋址,多任務,內存管理等,可進入虛擬模式
虛擬模式:1M尋址,多任務,內存管理等,很多指令用不了
1.3.2
DOS下尋址:段地址×16+偏移地址 = 物理地址
Win32尋址:段選擇器→段地址+偏移地址 = 線性地址
格式:xxxx:yyyyyyyy
xxxx中,低第二位標識1代表LDT的索引,0代表GDT的索引
TI=1,先找到GDT,再找到LDT(隨任務切換),再找到基址
TI=0,先找到GDT,再找到基址
1.3.3
分頁機制解決多任務內存碎片合併問題
目錄和頁表指定線性地址所對應的物理地址,出現虛擬內存
虛擬內存可以存儲內存不常用的數據,也可以存儲要訪問的數據
1.3.4
內存兩倍大小的交換文件用作虛擬內存(PageFile.sys)
每個程序都有4G的尋址空間,由時間片來控制
1.3.5
windows爲用戶安排好了一切,CIH病毒不能侵入NT內核
CS,DS,ES,SS用戶就不必關心了
1.3.6.1
8086:int n中斷,找到n×4處的地址,將Flag,CS,IP壓棧,執行中斷,iret使Flag,CS,IP出棧,繼續執行
80386:門,中斷門,自陷門,任務門,進入高優先級程序的入口
IDTR,高32位是IDT的地址,低16位是限長,每個中斷8個字節,包括門種類和入口地址xxxx:yyyyyyyy
中斷描述符表用戶無權改寫,自己無法寫中斷處理程序,int n也不會出現了
1.3.6.2
80386優先級:0訪問系統全部資源,1,2,3最低級,會執行一系列程序檢查越權操作
windows系統只有兩個0,3
一些指令不可用:lgdt,lldt,lidt等賦值指令
一些指令可用:sgdt,sldt,sidt等讀取指令
dll很多越權操作會算在用戶頭上,經常藍屏幕
用戶的越權操作會被判死刑,一點回旋餘地都沒有
2.1
DOS可執行文件和Win32可執行文件(PE文件)很不同
創建代碼+創建資源
.asm,.rc
2.1.2
不同版本的MASM32程序不一定兼容
2.3
ResourceWorkshop
Vc++
2.4
nmake
;model defination
.386 ;會用到80386的指令.386p可以使用特權指令\
.386基本上夠用了,.486,.586,.mmx等
.model flat, stdcall;.model 內存模式【,語言模式】【,其他模式】,\
Win32中內存模式只能選flat,意思是代碼段和數據段使用同一個4G段\
此時,FS,GS默認不使用\
語言模式指參數的傳遞次序和堆棧平衡辦法,Win32中只能用stdcall
option casemap: none
;指明程序對大小寫是否敏感,Win32對大小寫敏感所以必須寫上這條語句
;下面程序的結構\
;include
;數據段:可讀可寫的已經初始化的變量,_DATA,.data\
可讀可寫的未初始化的變量,緩衝區,.data?,不會佔用程序大小\
不可寫的常量,.const
;代碼段:_TEXT,不可寫,但是可以修改這個權限
;堆棧段:可寫,緩衝區溢出技術
;invoke僞指令,完成push和call的操作,實現Win32API的調用,編譯器可以檢查參數是否正確
;invoke MessageBox, NULL, offset szText, offset szCaption, MB_OK
;API函數的返回值,存入eax,或把指針存入eax,或建立一個緩衝區,把返回值存進去
;include,includelib
;標號,:和::的區別\
@@,@F本指令後第一個@@,@B本指令前第一個@@\
;全局變量,.data,.data?\
變量名 類型 初始值1,初始值2……\
變量名 類型 重複數量 dup (初始值1,初始值2……)\
類型,字節db,字dw,雙字dd,三字df,四字dq,10字節dt\
wordBuffer dw 100 dup (1, 2) ;0001,0002重複100遍\
szText db 'hello,world!' ;一個12字節的字符串\
page64,緩衝區定義和byte的靈活定義\
問號代表0
;局部變量\
local 變量名1【重複數量】【:類型】,……\
local必須緊跟proc指令\
類型不能用縮寫:byte,word,dword,fword,qword,tbyte\
類型也可以是Win32中的數據結構\
stWndClass WNDCLASS <>\
stWndClass WNDCLASS <1,1,1,1,1,1,1,1>\
ebp不要隨意使用,它用來存儲上一個程序的地址
;數據結構\
變量名引用stWndClass.lpfnWndProc\
指針引用 mov esi, offset stWndClass\
assume esi: ptr WNDCLASS\
mov eax, [esi].lpfnWndProc\
assume esi: nothing
;以不同的類型訪問變量
szBuffer db 1024 dup (?)
mov ax, word ptr szBuffer;必須指定長度,程序只用地址操作,不會執行越界檢查
bTest db 12h
wTest dw 1234h
dwTest dd 12345678h
mov al, bTest ;al = 12h
mov ax, word ptr bTest ;ax = 3412h
mov eax, dword ptr bTest ;eax = 78123412h
;時刻注意變量在內存中的排列!
;改進,movzx命令,位數少賦值給位數多時,用0填充\
movsx命令,用有符號數最高位填充