X86汇编学习笔记(实时更新)

数据宽度:事实上就是数据所占用的存储空间。

原码:最高位为符号位,其余位为数值本身的绝对值。

反码:正数的反码和原码相同。负数反码符号位为1,其余取反。

补码:正数的补码和原码相同。负数的补码相当于先取补码再+1。

无符号数的编码规则:即存多少就是多少,如1001 1010 即为9A。

有符号数的编码规则:最高位为1代表负数,最高位为0代表正数。

计算机只能通过位运算实现运算。

与运算:两个位均为1时,结果才为1。

或运算:只要有一个为1就是1

异或运算:不一样的时候是1(xor)

非运算(单目运算): 即取反

左移:全部左移若干位,高位丢弃,低位补0(shl)

右移:全部右移若干位,低位丢弃,高位补零(shr)或符号位(sar)

通过位运算实现四则运算

加:

1)进行异或(不考虑进位的情况下,异或得到的结果和加相同)

2)判断是否有进位(通过与运算实现)

3)与得到的数左移一位再与1)得到的结果继续异或

重复这几个过程,直到与运算得到的结果为0000 0000,则已得出最终结

减:

做减法过程与做加法相同,只不过减数符号位从0变成了1

而乘除在本质上是和加减一致的

通用寄存器(32位)

eax ebx ecx edx

esp ebp eip edi

标志寄存器

efl(32位) 每个位的含意不同

其第10位是DF位,当DF位为0,执行完movs指令(以及类似指令如stos),edi和edi的值+1/2/4,取决于操作了几个字节,当DF位为1时,为-1/2/4

bit 0

CF[carry flag] 若算数操作产生的结果在最高有效位发生进位或借位(减法)则将其置1,反之清零

通常用来指示无符号整型运算的溢出状态

bit 2

PF[parity flag] 如果结果的最低有效字节包含偶数个1位则置1,否则清零

利用PF可进行奇偶校验检查

bit 4

AF[auxiliary carry flag]

如果算术操作在结果的 第3位发生进位或错位则将该标志置1,否则清零

在BCD(binary-code decimal)算数运算中被使用

 bit 6

ZF[zero flag]

若结果为0则置1,反之清零

常与cmp(相当于sub,但是不储存结果,只影响标志寄存器)或test(相当于and,同样只影响标志寄存器)等指令一起使用

bit 7

SF[sign flag] 

被设置为有符号整型的最高有效位,0为正1为负

bit 11

OF[overflow flag] 

溢出标志OF用于反应有符号数加减运算所得结果是否溢出

判断溢出,无符号数运算看CF位

有符号数运算看OF位

bit 10

DF[direction flag]

std以及cld指令分别用于设置(置1)以及清除DF标志

内存

汇编指令中要将数据写入内存时,必须要指明数据宽度,mov byte ptr dr:[0x41f00c],1

大端模式:数据高位在地址低位,数据低位在地址高位

小端模式:数据低位在地址低位,数据高位在地址高位

常用指令

以下r代表通用寄存器,m代表内存,imm代表立即数,r8代表8位通用寄存器,以此类推

mov

注意数据宽度对齐

1.mov r/m,r

2.mov r,imm

add

1. add r/m,imm

2.add r/m,r

3.add r,r/m

其运算结果均储存在第一个操作目标

sub

与add类似,不过是在做减法

and

1.and r/m,imm

2.and r/m,r

3.and r,r/m

运算结果同样放在第一个操作目标处

xor

1.xor r/m,imm

2.xor r/m,r

3.xor r,r/m

not

not r/m(单目运算)

movs 

移动数据内存-内存

movs byte ptr es:[edi],byte ptr ds:[esi] 简写为movsb

于此类似还有 movsw(数据宽度为word) movsd(数据宽度为dword)

stos 将ax/ax/eax的值存储到 [edi]指定的内存单元

stosb stosw stosd

rep

重复次数取决于ecx中的值

mov ecx,10

rep  movsd 每执行一次ecx中值会-1

push

push r/m/imm

1.向堆栈中压入数据

2.自动修改栈顶指针esp的值

本质上可以通过mov,sub等指令合成

pop

栈顶值出栈,eip+4

jmp

jmp r/m/imm

修改eip的值,控制程序执行流

call

call r/m/imm

1.修改eip值(相当于jmp)

2.call下一个栈帧地址(高地址)压栈(相当于push)(目的是保存父函数eip的值)

leave

1.mov esp,ebp(返回父函数前将子函数栈顶esp抬高至ebp处)

2.pop ebp(此时esp指向的是prev_ebp,ebp被恢复为父栈底)

ret

1.栈顶指针指向的值存入eip(leave结束后首先将esp抬高,然后此时esp指向ret_addr,即父函数的eip),通过此指令将eip恢复

2.esp+4(32位),至此父函数状态得以恢复

jcc

类似jmp,但是否修改eip取决于标志寄存器的值

如jz,若z位为0,则不修改eip 

内存

堆栈:不需要主动申请,kernel自动分配

esp:栈顶指针寄存器,存储的是使用过的栈最低地址(由高地址向低地址增长)

eip:储存下一条执行地址

函数

指令的集合

执行函数:函数调用

1.jmp

2.call

通常用eax存放返回值,可以用寄存器存放参数,也可以通过堆栈传参,其值的取用通过取用esp+4*n实现

堆栈平衡

esp寻址:

即函数调用前后栈顶(esp)应不变

1.由于函数内部修改esp的值(如push)导致ret时esp不是原栈顶,函数内通过pop push入的值平衡

2.堆栈传参导致的,通过外平栈(在返回位置加入修改esp值指令)或内平栈(ret n 相当于返回时esp+n)平衡(传递完毕的参数不应该是栈顶)

ebp寻址:

call函数,call会将ret_addr(即call下一条指令压栈),之后由于要进入调用函数的栈帧,所以首先得push ebp保存父函数的栈底(高地址),然后再将ebp降低到esp的位置(栈顶指针不需要保存,因为栈帧相邻,而且父函数栈顶必定是子函数的栈顶),这步通过mov ebp,esp实现,之后再将esp-n则创立了一个新的栈帧。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值