win32汇编各寄存器常规功能

来源:互联网 发布:mac介质访问控制 编辑:程序博客网 时间:2024/06/06 13:56

学 Win32 汇编[16]: 常用寄存器的常规功能


通用寄存器EAX累加(Accumulator)寄存器AX(AH、AL)常用于乘、除法和函数返回值EBX基址(Base)寄存器BX(BH、BL)常做内存数据的指针, 或者说常以它为基址来访问内存.ECX计数器(Counter)寄存器CX(CH、CL)常做字符串和循环操作中的计数器EDX数据(Data)寄存器DX(DH、DL)常用于乘、除法和 I/O 指针ESI来源索引(Source Index)寄存器SI常做内存数据指针和源字符串指针EDI目的索引(Destination Index)寄存器DI常做内存数据指针和目的字符串指针ESP堆栈指针(Stack Point)寄存器SP只做堆栈的栈顶指针; 不能用于算术运算与数据传送EBP基址指针(Base Point)寄存器BP只做堆栈指针, 可以访问堆栈内任意地址, 经常用于中转 ESP 中的数据, 也常以它为基址来访问堆栈; 不能用于算术运算与数据传送指令指针寄存器EIP指令指针(Instruction Pointer)寄存器总是指向下一条指令的地址; 所有已执行的指令都被它指向过.标志寄存器EFLAGS

标志(Flag)寄存器:
EFLAGS 中的 32 位被分成 0-31 个二进制位分别使用;
第 0、2、4、6、7、11 位是状态标志位;
第 10 位是字符串操作控制标志位;
其他标志位一般不用或无权使用
 

0CF进位(Carry)标志目标无法容纳无符号算术运算的结果, 需要进位或借位时被设置; 可用 STC 指令设置, CLC 指令取消.1   2PF奇偶(Parity)标志低 8 位中有偶数个 1 时被设置3   4AF辅助(Auxiliary)标志使用 BCD 码运算导致 3 位到 4 位产生进位时被设置5   6ZF零(Zero)标志运算结果为 0 时被设置7SF符号(Sign)标志运算结果为负数时被设置8   9   10DF方向(Direction)标志字符串操作是从高位到低位时被设置; 可用 STD 指令设置, CLD 指令取消.11OF溢出(Overflow)标志因有符号运算的结果太宽而导致数据丢失时被设置...   31   ...     

其中的 EAX、ECX、EDX 三个寄存器相对自由些, 所以练习时用它们较多.

没理会段寄存器: CS、DS、SS、ES、FS、GS, 是因在 Win32 保护模式下编程它们不再重要了.

还有 FPU、MMX 系列寄存器, 等用到再说吧.


win32汇编中的sizeof
win32汇编中的sizeof不同于其它语言的sizeof ,这个是真正的sizeof,以字节为单位的。
看下例

szhello db 'hello,world!',0

mov eax,sizeof szhello

eax=?
答案是
eax=13
因为hello,world!为13个字节,然后0占一个,所以是13
变量命名风格
 前缀 含义
b byte
w word
dw dword
h 句柄
lp 指针
sz 以0结尾的字符串
lpsz 指向以0结尾的字符串的指针
f 表示浮点数
st 表示一个数据结构

全局变量下面的前缀为_ 局部变量的前缀为@
enter与leave
ENTER是建立当前函数的栈框架,即相当于以下两条指令:
      pushl   %ebp
      
movl   %ebp,%esp
    8)LEAVE是释放当前函数或者过程的栈框架,即相当于以下两条指令:

       movl ebpesp

      popl  ebp

   如果反汇编一个函数,很多时候会在函数进入和返回处,发现有类似如下形式的汇编语句:
       
      pushl   %ebp          ;ebp寄存器内容压栈,即保存main函数的上级调用函数的栈基地址
      movl   %esp,%ebp      ;esp值赋给ebp,设置 main函数的栈基址

      ...........          ;以上两条指令相当于 enter0,0
      ...........

      leave               ;将ebp值赋给esp,pop先前栈内的上级函数栈的基地址给ebp,恢复原栈基址

      ret                    ; main函数返回,回到上级调用

   这些语句就是用来创建和释放一个函数或者过程的栈框架的。
   原来编译器会自动在函数入口和出口处插入创建和释放栈框架的语句。
   函数被调用时:
    1) EIP/EBP成为新函数栈的边界
   函数被调用时,返回时的EIP首先被压入堆栈;创建栈框架时,上级函数栈的EBP被压入堆栈,与EIP一道行成新函数栈框架的边界
    2) EBP成为栈框架指针SFP,用来指示新函数栈的边界
   
栈框架建立后,EBP指向的栈的内容就是上一级函数栈的EBP,可以想象,通过EBP就可以把层层调用函数的栈都回朔遍历一遍,调试器就是利用这个特性实现backtrace功能的
    3) ESP总是作为栈指针指向栈顶,用来分配栈空间
   栈分配空间给函数局部变量时的语句通常就是给ESP减去一个常数值,例如,分配一个整型数据就是 ESP-4
    4) 函数的参数传递和局部变量访问可以通过SFP即EBP来实现
   由于栈框架指针永远指向当前函数的栈基地址,参数和局部变量访问通常为如下形式:
       +8+xx(%ebp)       ; 函数入口参数的的访问

       -xx(%ebp)         ; 函数局部变量访问
80x86堆栈的增长及PUSH和POP
1、堆栈向地址减小的方向增长
2、PUSH后,先压入堆栈,再减少ESP值;POP与之相反。
3、ESP指向堆栈顶的那个值,而不是堆栈的下一个空白处
通用寄存器的目的
1、EAX和AX:累加器,所有的I/O指令用它来与外部设备传送信息
2、EBX和BX:在计算存储单元地址时常用作基地址寄存器
3、ECX和CX:保存计数值
4、EDX和DX:做四字或二字运算时,可以把EDX(DX)和EAX(AX)组合在一起存放一个四字或二字长的数据,在对某些I/O操作时,DX可以放I/O的端口地址
5、ESP和SP:堆栈栈顶指针。
6、EBP和BP:基址寄存器
7、ESI和SI:源变址
8、EDI和DI:目的变址
invoke语句  
 invoke既可以调用WINDOWS API,也可以调用汇编子程序。
格式为invoke 程序名,参数1,参数2,。。。。
参数2先入堆栈,参数1再入堆栈,以此类推
如invoke mysubpro,eax,ecx
编译器会编译成下面这个模样:
push ecx
push eax
call mysubpro
类似于高级语言的条件选择语句,
.if 条件1
语句1
.else 条件2
语句2
....
.else
语句3
.endif
但实际编译后
1、对if ebx
2、对if eax 会翻译成or eax,eax
        je 0040100c如果eax为0,则该条件不满足,跳转到下一条语句或下个条件判断,0040100c是举例,即下个语句的地址。
循环语句
.while 条件
..........
..........
[.break[.if 退出条件]]
[.contine]
.endw
 
.repeat
...........
..........
[.break[.if 退出条件]]
[.contine]
.until 条件(或.untilcxz [条件])
标号与变量
1、标号
@@:标号
@F:前面一个标号
@B:后面一个标号
2、全局变量定义在.data和.data?内
3、局部变量用local指令定义
local 变量名1:类型,变量名2:类型
数据结构
1、声明
wndclass struct
....
.....
......
wndclass ends
2、定义
mystruct wndclass<1,1,...,1>
mystruct wndclass <>
3、使用
mov eax,mystruct.lpfnwndproc
 
mov esi,offset mystruct
assume esi: ptr WNDCLASS
mov eax,[esi].lpfnwndproc
 
.......
assume esi:nothing
变量使用
1、
mov eax,dword prt 变量名
2、
 sizeof:变量、数据类型或数据结构以字节为单位的长度。
 lengthof:取得变量中数据的项数。
3、
offset:取变量地址的伪操作符,在编译时完成
addr:在运行时完成取地址
子程序
1、定义
子程序名 proc [距离][语言类型][可视区域][USERS 寄存器列表][,参数:类型]...[VARARG]local 局部变量列表
..............
...............
...............
子程序名 endp
2、如果在未定义前使用,要声明、
函数名 proto [距离][语言][参数1]:数据类型,[参数2]:数据类型,...............
保护模式下的段的寻址
一、虚拟地址为:
XXXX:YYYYYYYYYYY
二、16位的段寄存器只有高13位表示索引值,剩下的3个数据位中,第0、1位表示程序的当前优先级,第2位TI位用来表示在段描述符的位置;TI=0表示在GDT中,TI=1表示在LDT中。
三、
1、首先要看XXXX的TI位是否为0,如果是的话,则先从GDTR寄存器中获取GDT的地址,然后,在GDT中根据段寄存器的索引值来等到段描述符,从而得到段的起始地址。
2、如果XXXX的TI位为1,表示段寄存器存放的是LDT中的段,首先从GDTR寄存器中获取GDT的地址,然后从LDTR中获得LDT在GDT中的索引值,以这个位置索引在GDT中得到LDT段的位置,最后使用表示索引值的高13位来在LDT中寻找




原创粉丝点击