●●●eax,ebx,ecx,edx等等寄存器书上讲得太抽象了?有些不懂,或者是理解错误的地方,请大家指点
书上说,AX累加器,bx,cx,dx是通用寄存器,分别用作基址变址,
计数器,数据,那么eax,ebx,ecx,edx也分别是累加器,基址变址,计数器,数据 吧?
基址变址:是什么意思?
下面代码为什么GetModuleHandle的返回值默认在eax里面,不在edx,ebx,ecx里面呢?eax是累加器,难道说累加器,
是专门得到函数的返回值得么?
-----------------------------------------------------
start:
invokeGetModuleHandle,NULL
movhInstance,eax
invokeDialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invokeExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
endstart
-----------------------------
又如下面代码,怎么又把数据村到esi里面了,原来都是存在eax里面的?
又突然冒来个pushebp? ebp又是做什么的?还有就是movfs:[0],esp这句话也不懂。
即便看了教材,也对应不上这寄存器的含义,书上讲得太抽象了?麻烦各位给讲讲,谢谢了
--------------------------
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
includewindows.inc
includeuser32.inc
includelibuser32.lib
includekernel32.inc
includelibkernel32.lib
includecomdlg32.inc
includelibcomdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAINequ1000
DLG_MAINequ1000
IDC_INFOequ1001
IDM_MAINequ2000
IDM_OPENequ2001
IDM_EXITequ2002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstancedd?
hRichEditdd?
hWinMaindd?
hWinEditdd?
szFileNamedbMAX_PATH dup (?)
.const
szDllEditdb'RichEd20.dll',0
szClassEditdb'RichEdit20A',0
szFontdb'宋体',0
szExtPedb'PE Files',0,'*.exe;*.dll;*.scr;*.fon;*.drv',0
db'All Files(*.*)',0,'*.*',0,0
szErrdb'文件格式错误!',0
szErrFormatdb'这个文件不是PE格式的文件!',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_AppendInfoproc_lpsz
local@stCR:CHARRANGE
pushad
invokeGetWindowTextLength,hWinEdit
mov@stCR.cpMin,eax
mov@stCR.cpMax,eax
invokeSendMessage,hWinEdit,EM_EXSETSEL,0,addr @stCR
invokeSendMessage,hWinEdit,EM_REPLACESEL,FALSE,_lpsz
popad
ret
_AppendInfoendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include_ProcessPeFile.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Initproc
local@stCf:CHARFORMAT
invokeGetDlgItem,hWinMain,IDC_INFO
movhWinEdit,eax
invokeLoadIcon,hInstance,ICO_MAIN
invokeSendMessage,hWinMain,WM_SETICON,ICON_BIG,eax
invokeSendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0
invokeRtlZeroMemory,addr @stCf,sizeof @stCf
mov@stCf.cbSize,sizeof @stCf
mov@stCf.yHeight,9 * 20
mov@stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLD
invokelstrcpy,addr @stCf.szFaceName,addr szFont
invokeSendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCf
invokeSendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1
ret
_Initendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 错误 Handler
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Handlerproc_lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
pushad
movesi,_lpExceptionRecord
movedi,_lpContext
assumeesi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
moveax,_lpSEH
push[eax + 0ch]
pop[edi].regEbp
push[eax + 8]
pop[edi].regEip
pusheax
pop[edi].regEsp
assumeesi:nothing,edi:nothing
popad
moveax,ExceptionContinueExecution
ret
_Handlerendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_OpenFileproc
local@stOF:OPENFILENAME
local@hFile,@dwFileSize,@hMapFile,@lpMemory
invokeRtlZeroMemory,addr @stOF,sizeof @stOF
mov@stOF.lStructSize,sizeof @stOF
pushhWinMain
pop@stOF.hwndOwner
mov@stOF.lpstrFilter,offset szExtPe
mov@stOF.lpstrFile,offset szFileName
mov@stOF.nMaxFile,MAX_PATH
mov@stOF.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
invokeGetOpenFileName,addr @stOF
.if! eax
jmp@F
.endif
;********************************************************************
; 打开文件并建立文件 Mapping
;********************************************************************
invokeCreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ or \
FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
.ifeax !=INVALID_HANDLE_VALUE
mov@hFile,eax
invokeGetFileSize,eax,NULL
mov@dwFileSize,eax
.ifeax
invokeCreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL
.ifeax
mov@hMapFile,eax
invokeMapViewOfFile,eax,FILE_MAP_READ,0,0,0
.ifeax
mov@lpMemory,eax
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
assumefs:nothing
pushebp
pushoffset _ErrFormat
pushoffset _Handler
pushfs:[0]
movfs:[0],esp
;********************************************************************
; 检测 PE 文件是否有效
;********************************************************************
movesi,@lpMemory
assumeesi:ptr IMAGE_DOS_HEADER
.if[esi].e_magic != IMAGE_DOS_SIGNATURE
jmp_ErrFormat
.endif
addesi,[esi].e_lfanew
assumeesi:ptr IMAGE_NT_HEADERS
.if[esi].Signature != IMAGE_NT_SIGNATURE
jmp_ErrFormat
.endif
invoke_ProcessPeFile,@lpMemory,esi,@dwFileSize
jmp_ErrorExit
_ErrFormat:
invokeMessageBox,hWinMain,addr szErrFormat,NULL,MB_OK
_ErrorExit:
popfs:[0]
addesp,0ch
invokeUnmapViewOfFile,@lpMemory
.endif
invokeCloseHandle,@hMapFile
.endif
invokeCloseHandle,@hFile
.endif
.endif
@@:
ret
_OpenFileendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMainprocuses ebx edi esi hWnd,wMsg,wParam,lParam
moveax,wMsg
.ifeax == WM_CLOSE
invokeEndDialog,hWnd,NULL
.elseifeax == WM_INITDIALOG
pushhWnd
pophWinMain
call_Init
.elseifeax == WM_COMMAND
moveax,wParam
.ifax ==IDM_OPEN
call_OpenFile
.elseifax ==IDM_EXIT
invokeEndDialog,hWnd,NULL
.endif
.else
moveax,FALSE
ret
.endif
moveax,TRUE
ret
_ProcDlgMainendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invokeLoadLibrary,offset szDllEdit
movhRichEdit,eax
invokeGetModuleHandle,NULL
movhInstance,eax
invokeDialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invokeFreeLibrary,hRichEdit
invokeExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
endstart
[解决办法]
高级语言特性+编译器,通常将函数的返回值放在EAX中(单一返回值直接放EAX,如果多个返回值,则EAX中存放指针)。
至于寻址方式,你可以随便找本汇编的教材看一下,看过之后,看的懂寻址寻到哪个地址就行了。
至于具体是属于哪种寻址方式,就没必要深究了。
[解决办法]
1、变址寄存器
32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响
高16位的数据。
寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,
用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。
变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。
它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特
殊的功能。
2、指针寄存器
32位CPU有2个32位通用寄存器EBP和ESP。其低16位对应先前CPU中的SBP和SP,对低16位数据的存取,不影
响高16位的数据。
寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register),主要用于存放堆栈内存储单元的偏移量,
用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。
指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。
它们主要用于访问堆栈内的存储单元,并且规定:
BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;
SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。
[解决办法]
你的理解有问题 api函数规定默认是是用eax返回值 所以大家一般都遵守这个规定
所以自己写的函数一般也是如此 即使值在其他寄存器 比如
myStrlenproc uses ebx edi esi _lpOut
.....
mov eax, ebx 返回值放在eax
ret
myStrlenendp
除了寄存器EBP、ESP用于指令外, 其他寄存器都可以随便使用, 不一定按照书上说的功能那样用
[解决办法]
在8086中,寄存器是ax、bx等,在386之后,寄存器扩展到了32位,eax的低16位就是ax,ebx的低16位是bx,原本的16位寄存器都可以继续使用,以字母e开头表示使用32位寄存器。32寄存器的用法与16位类似,例如32位程序用ecx做记数器,主要一点差异是,32位程序中任意通用寄存器均可用做间址和变址。在X64处理器中,用rax、rbx表示64位寄存器,eax表示rax的低32位,ax表示rax的低16位。
在32位程序中,32位以内的函数返回值都通过eax寄存器来传递。
fs是386之后增加的段寄存器,在Windows应用程序中,fs:[0]用来保存异常捕获设置。