汇编基础
Wirte by 021. Leave a message if i messed up ! : )
寄存器
32位
- 提供三种容器寄存器 : 8 , 16 , 32.
64位
- 提供4中容器寄存器 : 8 ,16 ,32 ,64.
通用寄存器32位
用户自定义使用寄存器
数据宽度为32位 多余的丢弃
EAX
- 返回值容器
ECX
- REP执行计数器
EDX
EBX
ESP
- 栈指针寄存器,栈内存起始位置到ESP指针位置为已使用内存
EBP
- 栈底
ESI
- movs 使用
EDI
- movs 使用
EFL
- 内存地址高低方向位
非通用寄存器
EIP
- cpu下次执行时会找EIP存的值
指令
mov
- 操作数数据宽度需要相同
1
2
3
4
5
6
7
8
9
10
11
12
13mov eax,1 ; 将1存进eax寄存器。
mov ecx,1 ; 将1存进ecx寄存器。
mov eax,ecx ; 将ecx存进eax寄存器
x64模拟器:
%rax 作为函数返回值使用。
%rsp 栈指针寄存器,指向栈顶
%rdi,%rsi,%rdx,%rcx,%r8,%r9 用作函数参数,依次对应第1参数,第2参数。。。
%rbx,%rbp,%r12,%r13,%14,%15 用作数据存储,遵循被调用者使用规则,简单说就是随便用,调用子函数之前要备份它,以防他被修改
%r10,%r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值
add 加法
1
add eax,ecx; 将ecx 与 eax 相加 存进eax寄存器;
sub 减法
1
sub eax,ecx; 将ecx 与 eax 相减 存进eax寄存器;
AND 与运算
1
AND eax,ecx; 将ecx 与 eax 与运算 存进eax寄存器;
or 或运算
1
or eax,ecx; 将ecx 与 eax 与或算 存进eax寄存器;
xor 异或运算
1
xor eax,ecx; 将ecx 与 eax 与异或算 存进eax寄存器;
NOT 非运算
1
not eax, 将eax取反 ,存进eax寄存器;
**movs 从内存到内存 **
- 每复制一次 内存地址自增长当前数据宽度位
1
2
3
4
5
6Movs byte ptr es:[edi] , byte ptr ds:[esi]
Movs byte ptr es:[0x00000000] , byte ptr ds:[0x00000001]
ELF
stos 将AI/AX/EAX的值存储到[EDI]指定的内存单元
1
2
3
STOS WORD PTR ES:[edi]
- REP 重复执行 ,依赖ecx 寄存器的计数器 10进制,每次执行ecx值减一
JMP 寄存器/立即数/内存
- 修改EIP的值
1
2
3
jmp dword ptr ds:[eax]; 将eax的地址值,赋给EIP,cpu下次执行的将是eax里面的指令.CALL
修改EIP值,再将ESP-4,并将栈顶值压入在ESP-4的地址中
RET
1,将当前栈顶的值放进EIP中
2,将当前ESP指针值+4
内存地址
0x0000000
1
数据宽度:32位.
内存基本单元= 1byte = 8bit
往内存中写数据
mov 数据宽度 ptr ds:[内存地址] ,值 , mov byte ptr ds:[0x00000000] ,1
mov 数据宽度 ptr ds:[内存地址] ,值 , mov word ptr ds:[0x00000000] ,1 ; 单字宽度
mov 数据宽度 ptr ds:[内存地址] ,值 , mov Dword ptr ds:[0x00000000] ,1; 双字宽度
mov 数据宽度 ptr ds:[内存地址] ,值 , mov Dword ptr ds:[0x00000000] ,eax; 将寄存器写入内存
mov 数据宽度 ptr ds:[内存地址] ,值 , mov eax, Dword ptr ds:[0x00000000] ; 将内存写入寄存器
mov 数据宽度 ptr ds:[内存地址] ,值 , mov eax, Dword ptr ds:[ecx+4] ; 将ecx内存地址+4的位置值写入寄存器
存储模式
小端模式 x86
1
2
3
4数据低位在低位,数据高位在高位.
mov word ptr ds:[0x00000000],0x1a2c , 0x00000000[1a], 0x00000001[2c].大端模式 arm
1
2
3
4数据低位在高位,数据高位在低位.
mov word ptr ds:[0x00000000],0x1a2c , 0x00000000[2c], 0x00000001[1a].
堆栈
PUSH压栈
- push指令将数据压入栈中,并移动栈针ESP ,(eps - 数据宽度)
pop弹栈
pop指令将数据弹出栈外,并移动栈针ESP ,(eps + 数据宽度)
pop eax; 将栈顶的值存入eax中,esp指针 + eax值的数据宽度
函数
- JMP调用函数(通常不用)
CALL()调用函数**
- 基本函数调用流程
1 | 求 10 + 7 = ? |
- 堆栈函数与平衡
1 | 求 1 + 2 + 3 + 4 = ? |
ESP栈顶寻址
1 | 求 1 + 2 + 3 + 4 = ? |
EBP栈底寻址
1 | 求 1+2 = ? |
JCC指令集
- JCC指令根据标志寄存器值的标志位来修改EIP的,从而实现执行跳转
标志寄存器
- 运算相关指令都会影响标志寄存器
JCC指令 | 中文含义 | 英文原意 | 检查符号位 | 典型C应用 |
---|---|---|---|---|
JZ/JE |
若为0则跳转;若相等则跳转 | jump if zero;jump if equal | ZF=1 |
if (i == j);if (i == 0); |
JNZ/JNE |
若不为0则跳转;若不相等则跳转 | jump if not zero;jump if not equal | ZF=0 |
if (i != j);if (i != 0); |
JS |
若为负则跳转 | jump if sign | SF=1 |
if (i < 0); |
JNS |
若为正则跳转 | jump if not sign | SF=0 |
if (i > 0); |
JP/JPE |
若1出现次数为偶数则跳转 | jump if Parity (Even) | PF=1 |
(null) |
JNP/JPO |
若1出现次数为奇数则跳转 | jump if not parity (odd) | PF=0 |
(null) |
JO |
若溢出则跳转 | jump if overflow | OF=1 |
(null) |
JNO |
若无溢出则跳转 | jump if not overflow | OF=0 |
(null) |
JC/JB/JNAE |
若进位则跳转;若低于则跳转;若不高于等于则跳转 | jump if carry;jump if below;jump if not above equal | CF=1 |
if (i < j); |
JNC/JNB/JAE |
若无进位则跳转;若不低于则跳转;若高于等于则跳转; | jump if not carry;jump if not below;jump if above equal | CF=0 |
if (i >= j); |
JBE/JNA |
若低于等于则跳转;若不高于则跳转 | jump if below equal;jump if not above | ZF=1或CF=1 |
if (i <= j); |
JNBE/JA |
若不低于等于则跳转;若高于则跳转 | jump if not below equal;jump if above | ZF=0或CF=0 |
if (i > j); |
JL/JNGE |
若小于则跳转;若不大于等于则跳转 | jump if less;jump if not greater equal jump | SF != OF |
if (si < sj); |
JNL/JGE |
若不小于则跳转;若大于等于则跳转; | jump if not less;jump if greater equal | SF = OF |
if (si >= sj); |
JLE/JNG |
若小于等于则跳转;若不大于则跳转 | jump if less equal;jump if not greater | ZF != OF 或 ZF=1 |
if (si <= sj); |
JNLE/JG |
若不小于等于则跳转;若大于则跳转 | jump if not less equal;jump if greater | SF=0F 且 ZF=0 |
if(si>sj) |