在汇编中,变量都是放在.data或者.data?中的,其中分为全局变量和局部变量。
全局变量:
.data
wHour dw ? #未初始化的word类型
wMinute dw 10 #初始化为10的word类型
word_Buffer dw 100 dup(1,2) #200个字
szBuffer byte 1024 dup(?) #1024字节的缓冲区
szText db 'Hello World' #字符串11个字节
szText db 'Hello World',0dh,0ah,'Hello again',0dh,0ah,0 #0dh,0ah为换行符
(.data?段中无法指定初始化值,默认初始值为0)
局部变量
简述:在进入子程序的时候,通过修改栈指针esp来留出需要的空间,在用ret返回的时候就通过恢复esp来丢弃这个空间
local loc1[1024]:byte #定义了1024自己长的局部变量loc1
local loc2 #dword(默认)的局部变量
local loc3:WNDCLASS #一个WNDCLASS的数据结构
注:可以使用sizeof和lengthof来计算变量的长度
例:
szHello db 'Hello',0dh,0ah
db 'World',0
sizeof szHello的值为7
改为stlen来计算这个字符串长度
变量是利用指针来操作的
lea eax,[ebp-4] 计算出地址放到eax中
但是在invoke伪指令参数用到局部变量的时候不能用lea指令,只能用addr来代替从而获得变量的地址
但是,这里又会有莫名其妙的问题:
invoke Test,eax,addr szHello
这句会被翻译成:
lea eax,[ebx-4]
push eax
push eax
call Test
所以说eax不能用在addr的前面
下面还有一个例子是对局部变量的分析
源代码:
1 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 ;数据段 3 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4 .data 5 szCaption db '来自deadfish', 0 6 szText db 'Hello, win32 assembly lanuage', 0 7 8 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 9 ;代码段 10 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 11 .code 12 start: 13 call TestPro 14 invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK 15 invoke ExitProcess,NULL 16 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 17 ;子程序 18 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 19 TestPro proc 20 local @loc1:dword,@loc2:word 21 local @loc3:byte 22 ;总共定义了7个字节的局部变量 23 mov eax,@loc1 24 mov ax,@loc2 25 mov al,@loc3 26 ret 27 TestPro endp
反汇编之后:
1 00401000 >/$ E8 1A000000 call 02_1.0040101F 2 00401005 |. 6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL 3 00401007 |. 68 00304000 push 02_1.00403000 ; |Title = "来自deadfish" 4 0040100C |. 68 0D304000 push 02_1.0040300D ; |Text = "Hello, win32 assembly lanuage" 5 00401011 |. 6A 00 push 0x0 ; |hOwner = NULL 6 00401013 |. E8 1A000000 call <jmp.&user32.MessageBoxA> ; MessageBoxA 7 00401018 |. 6A 00 push 0x0 ; /ExitCode = 0x0 8 0040101A . E8 19000000 call <jmp.&kernel32.ExitProcess> ; ExitProcess 9 0040101F /$ 55 push ebp ;保存ebp的值 10 00401020 |. 8BEC mov ebp,esp ;把esp的值保存到ebp中 所以ebp的值很重要,不能随意改动,否则在退出子程序的是会出错 11 00401022 |. 83C4 F8 add esp,-0x8 ;从栈申请8字节的空间给局部变量 12 00401025 |. 8B45 FC mov eax,[local.1] ;赋值 这里就是通过ebp来指向局部变量的 13 00401028 |. 66:8B45 FA mov ax,word ptr ss:[ebp-0x6] 14 0040102C |. 8A45 F9 mov al,byte ptr ss:[ebp-0x7] 15 0040102F |. C9 leave ;完成恢复功能,这里相当于 mov esp,ebp pop ebp 16 00401030 . C3 retn 17 00401031 CC int3 18 00401032 $- FF25 08204000 jmp dword ptr ds:[<&user32.MessageBoxA>] ; user32.MessageBoxA 19 00401038 .- FF25 00204000 jmp dword ptr ds:[<&kernel32.ExitProcess>; kernel32.ExitProcess
然后再变量中还有一个要注意的:
.data
bTest1 db 12h
wTest1 dw 1234h
dTest1 dd 12345678h
...
.code
...
mov al,bTest ;al=12h
mov ax,word ptr wTest1 ;ax = 3412h
mov eax,dword ptr dTest1 ;eax = 78563412h
这样在运行之后的现象是因为.data的东西是按照高数据高地址的(8086汇编中就可以知道了)
要避免这种情况,用movzx代替mov即可