汇编期末复习的一些碎碎念
概念
算数逻辑移位
- 逻辑移位:不考虑符号位,空位补零
- 算术移位:有符号的
- 正数与逻辑移位相同
- 负数补码:高位补1低位补0,符号位要跟着一起移动
32位浮点数编码
32=1符号位+8指数+23有效数字
- 符号位:0正1负
- 指数:阶码(2的幂次数),是移码,$M=2^{n-1}-1=127$
- 有效数字:小数点后面的,小数点前是1
注意进制转换
操作数
- 双操作数——(目的 源)
MOV
ADD
LEA
- 单操作数——可能是目的/源/目的+源
INC
PUSH
CALL
- 无操作数
NOP
CLC
HLT
寄存器
- eax:累加器,加法乘法指令的缺省寄存器
- 32位寄存器
- ax是低16位
- al是低8位,ah是高8位
- ebx:基地址寄存器,在内存寻址时存放基地址
- ebp:基址指针,栈底
- esp:栈顶指针,栈顶是低地址,压入数据越多,esp越小
- eip:指示下一条运行指令的地址
- ecx:计数器
指令
数值
sub eax, 1
==dec eax
:减1,与cmp eax, 1
以及add eax, 0xFFFFFFFF
不同是因为标志位cmp eax, ebx
:通过减法运算来影响标志位test eax, ebx
:通过与运算来影响标志位,- 通常用来测试寄存器是否为空
- test和and的关系类似cmp和sub
- sal|sar算术移位,shl|shr逻辑移位
add|sub eax, ebx
结果保存在eax,即计算eax=eax+ebx
跳转
jmp
:无条件跳转je
:jump when equal,ZF=1时(零标志位)jge
:jump when greater or equaljne
:jump when not equaljnz
:jump when not zerocall 函数地址
: 将函数地址的下一条地址压入栈,将函数内操作的第一个地址放入EIP,汇编语言CALL和RET指令:调用一个过程 (biancheng.net)ret
把之前call放进堆栈中的地址弹回EIP
传输
lea op1, op2
:将op2的有效地址传输到op1(寄存器)mov op1, op2
只允许一个为寄存器
堆栈
push eax
:将eax压入栈,esp-=4
others
loop op
==dec ecx
+jnz op
- 先ecx–
- 再判断ecx是否为0,不为0则跳转
寻址
- 寄存器寻址
寄存器在CPU内部,不需要执行系统总线周期,快 - 立即数寻址
立即数-操作数在指令代码中,只能是源操作数 - 存储器寻址
CPU需要访问内存,此时的指令中要给出操作数的内存地址- 直接寻址
使用位移量EA,变量名称实质上是符号位移量[偏移的字节]
、[变量名]
- 寄存器间接寻址
EA直接由地址指针寄存器:SI, DI, BX, BP中获得[寄存器]
- 基址寻址&变址寻址
偏移量=地址指针寄存器(4个中的1个)中的内容+指令中的位移量
基址-BX/BP, 变址-SI/DI - 基址变址寻址
偏移量=基址指针寄存器+变址寄存器+指令中的位移量
- 直接寻址
函数调用
- cdecl:C的默认,所有参数从右到左依次入栈,手动清栈。不会要求调用者传递多少参数,可用于传递不定参数
- stdcall:C++ 的标准调用方式:所有参数从右到左依次入栈,自动清栈
- fastcall:使用寄存器传递函数参数
- 函数的返回值一般在寄存器eax
- 函数传参顺序:从右到左
大端小端
大端更自然
1字=16比特
碎碎念
32位类型:(unsigned)int, float
16位:short
push 对esp,ebp,4字节=32位
push ecx
和add esp, 0xFFFFFFFC
对esp的作用相同
汇编指令对操作数的要求(寄存器、立即数、地址)
- mov 只允许一个为存储器寻址
- [eax]是寄存器间接寻址,属于存储器寻址,表示将eax中的内容作为地址,去相应地址中找数据
- [1000H]是直接寻址,表示去1000H这个位置找数据
- add和sub
- 源操作数(2nd)可以为通用寄存器、内存单元、立即数
- 目的操作数(1st)可以为通用寄存器、内存单元
- lea 作用是把源操作数的地址放进目标操作数中,源操作数必须是内存操作数,目标操作数只能是16位通用寄存器,因为有效地址是16位
函数开辟栈帧的指令是push ebp、mov ebp,esp;
关闭:mov esp,ebp、pop ebp
2push+1call,esp减4减4减4
x-FFFFFFFF
==x+1
例题分析
题:C语言条件跳转中a<b对应的汇编的汇编代码是(A)
- A. mov eax, [a]; cmp eax, [b]; jge XXX;
- B. mov eax, [a]; cmp eax, [b]; jl XXX;
- C. mov eax, [a]; cmp eax, [b]; jle XXX;
- D. mov eax, [a]; cmp eax, [b]; jg XXX;
解:jge是当大于等于时跳转。C语言中if(a<b)
换句话说就是a>=b时才跳转。
题:F是函数
1 | F: |
解:
函数的调用方式是_cdecl
- 观察ret
ret 8
结束时自动清理堆栈,是stdcall或fastcallret
没有修改堆栈,需函数结束后手动清理
- 观察ret
函数F有1个参数
- call之前push的次数就是参数的个数
还原成C代码
1
2
3
4
5int F(int arg0){
if(arg0<=1)
return 1;
return F(arg0-1)+F(arg0-2);
}