;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcFile proc
local @hFile,@hFileNew,@dwBytesRead
local @szNewFile[MAX_PATH]:byte
local @szReadBuffer[512]:byte
;********************************************************************
; 打开文件
;********************************************************************
invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,\
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE
invoke MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONEXCLAMATION
ret
.endif
mov @hFile,eax
;********************************************************************
; 创建输出文件
;********************************************************************
invoke lstrcpy,addr @szNewFile,addr szFileName
invoke lstrcat,addr @szNewFile,addr szNewFile
invoke CreateFile,addr @szNewFile,GENERIC_WRITE,FILE_SHARE_READ,\
0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE
invoke MessageBox,hWinMain,addr szErrCreateFile,NULL,MB_OK or MB_ICONEXCLAMATION
invoke CloseHandle,@hFile
ret
.endif
mov @hFileNew,eax
;********************************************************************
; 循环读出文件并处理每个字节
;********************************************************************
xor eax,eax
mov @dwBytesRead,eax
.while TRUE
lea esi,@szReadBuffer
invoke ReadFile,@hFile,esi,sizeof @szReadBuffer,addr @dwBytesRead,0
.break .if ! @dwBytesRead
invoke _FormatText,esi,@dwBytesRead,@hFileNew
.endw
invoke CloseHandle,@hFile
invoke CloseHandle,@hFileNew
invoke wsprintf,addr @szReadBuffer,addr szSuccees,addr @szNewFile
invoke MessageBox,hWinMain,addr @szReadBuffer,addr szSucceesCap,MB_OK
ret
_ProcFile endp
以上代码摘自
Windows.环境下32位汇编语言程序设计(第2版)附属光盘\Chapter10\FormatText
★疑问点的是以下这两句为什么要先用lea取得地址放在esi里面 然后在invoke函数里面调用
为什么不用 直接在invoke函数里面 用 addr @szReadBuffer???
lea esi,@szReadBuffer
invoke ReadFile,@hFile,esi,sizeof @szReadBuffer,addr @dwBytesRead,0
★我也查了一个资料,找到了如下的答案,但是以上的情况应该不属于这种情况才对啊
这个问题困扰我很久,以致让我对于win32汇编的局部变量的地址的取法有些困扰,到底什么时候
可以用addr 什么时候又必须用lea取呢?
——————————————网络摘取答案开始-----------------------------
addr 局部变量名和全局变量名
当addr后跟全局变量名的时候,用法和offset是相同的;
当addr后面跟局部变量名的时候,编译器会自动用lea指令先把地址取到eax中,然后用eax来代替变量地址使用。
注意addr伪操作符只能在invoke的参数中使用,不能用在类似于下列的场合:
mov eax,addr 局部变量名 ;注意:错误用法
假设在一个子程序中有如下invoke指令:
invoke Test, eax, addr szHello
其中Test是一个需要两个参数的子程序,szHello是一个局部变量,会发生什么结果呢?编译器会把invoke伪指令和addr翻译成下面这个模样:
lea eax,[ebp-4]
push eax ;参数2:addr szHello
push eax ;参数1:eax
call Test
发现了什么?到push第一个参数eax之前,eax的值已经被lea eax,[ebp-4]指令覆盖了!也就是说,要用到的eax的值不再有效,所以,当在invoke中使用addr伪操作符时,注意在它的前面不能用eax,否则eax的值会被覆盖掉,当然eax在addr的后面的参数中用是可以的。
——————————————网络摘取答案结束-----------------------------
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)