汇编重修
感觉自己的汇编很依托,当时入门太匆忙了,假期重新学了一点(可能依旧依托
前置知识
原码反码补码(重点是负数
1 | 原码:最高位为符号位 |
一些运算
- 与运算 AND(&) 两个数都为1时,结果为1
- 或运算 OR(|) 只要有一个为1,结果为1
- 异或 XOR(^) 不一样的时候是1 xor eax,eax 清零寄存器
- 非运算 NOT(~) 0就是1,1就是0单目运算
- 左移 SHL/SAL(<<) 高位丢弃,低位补0 (左边高位,右边低位)
- 右移 高位丢弃(>>)
SHR 高位补0
SAR 最高位补符号位,保持符号不变 - 循环左移ROL 左移,最左边的到最右边 rol eax,1
- 循环右移ROR 右移,最右边的到最左边 ror eax,1
寄存器
1 | 32位 16位 8位 |
在进行数据传送或者运算时,要注意指令的两个操作对象的位数应该是一致的,例如:
1 | mov ax, bx |
以上指令都是正确的。
而:
1 | mov ax, bl (在8位寄存器和16位寄存器之间传送数据) |
以上都是错误的指令,错误原因是指令的两个操作对象位数不一致。
(这里是一些以前没注意的点)
1.在add的时候,有时候会遇到溢出的情况,需要把溢出舍掉,留低位,比如:
1 | mov ax,9000H; |
add之后,ax中的值原本是12000H,但是真正储存的2000H,1被舍了。
还有
1 | mov ax,9090H; |
因为al中只能存储两位16进制的数据,所以哪怕现在,本应该al的值为120H,但是这里1被舍弃。
最终ax为9020H
在上面这个情况中,al作为一个独立的8位寄存器使用
2.8086cpu给出物理地址的方法
8086采用在内部用两个16位地址合成的方法来形成一个20位的物理地址。
流程如下
地址加法器的操作:物理地址=段地址*16(左移4位)+偏移地址
为什么要用这种方式加密,这里王爽老师给了一个很通俗的例子
这样做的好处在于,增加了cpu的寻址能力。如果只简单的发出,只能传16位的地址。但是通过这样的方式,可以送出20位的地址。
3.段的概念
并不是内存分段了,而是我们可以用分段的方式管理内存(因为在2中,我们知道物理地址是由 段地址*16+偏移地址形成的)
cpu会用不同的
段寄存器4个:CS DS SS ES
区别程序和数据的方式:如果段地址是ds,则存放数据,如果段地址是cs,则存放指令
数据:[[rax]][数字]
栈:SS:SP表示栈顶(32位仍沿用这一方式,64位则用rsp代替了这一概念)
32位:SS提供基址,ESP提供栈的偏移地址
64位:RSP表示栈顶
压栈过程:esp=esp-4,存入数据
fs段寄存器:指向线程环境块(TEB)
fs $+20 进程id 线程id
fs $+30 进程环境块(TEB)指针
PEB结构:
$+2 是否正在被调试
$+68 NtGlobalFlag (拖入调试的话会变成0x70)
数据传输指令
push 压栈
pop 出栈
xchg 交换两个操作数的值
lea 取地址(相当于c的&
算术运算
add 加
sub 减
mul 无符号乘法
默认eax为被乘数,操作数为乘数
mov ebx eax=eax*ebx 结果储存在ebx中
imul 有符号乘法
单操作数:默认被乘数为eax ,同mul
双操作数:imul ebx,ecx 结果储存在ebx
三操作数:imul data,srm,imm 计算srm*imm,结果储存在data
div 无符号除法
被除数默认是edx:eax,操作数为除数,结果:
- 商储存在eax
- 余数储存在edx(需要确保edx被清零,或正确设置)
mov edx,0
mov eax,15
mov ecx ,3
div ecx
结果:
eax=5
edx=0
idiv 有符号除法
和div基本相同,但是需要在开启前设置cdq指令
mov eax,-15
cdq ;拓展符号位到edx
mov ecx,3
idiv ecx
结果:
eax=-5
edx=0
inc 自增(increase+1) inc eax
dec 自减(decrease-1) dec eax
逻辑比较指令
cmp eax,ebx ;对操作数进行减法运算
如果eax==ebx,则ZF=1,可以通过je,jz跳转
cmp影响的标志位有CF,ZF,SF,OF,PF,AF
test eax,ebx ;按位与,只更新标志寄存器不储存结果(ZF)
条件跳转指令
常用:
je/jz 相等,ZF=1
jne/jnz 不相等,ZF=0
jg 大于跳转
jl 小于跳转
jge 大于等于跳转
jle 小于等于跳转
loop 循环跳转
int 调用中断
iret 从中断返回

call:把下一条指令压栈和jmp
ret:返回到call下一行的执行代码
栈操作指令
push
pop
pushad:eax,ecx,edx,ebx,esp,ebp,esi,edi
popad:反pushad弹出
pushfd:压栈标志寄存器EFLAGS
popfd:反pushad弹出
enter:设置栈帧,将ebp压栈,设置新的ebp为局部变量并分配空间
leave:恢复栈帧,将ebp的值恢复到esp然后弹出原ebp
mov esp,ebp
pop ebp
字符串操作指令
1 | mov ecx,length |
复制字节
常用于memcpy,strcpy
rep重复下面的操作直到ecx=0
1 | mov esi,offset str_userinput ;用户输入的字符串 |
比较字符
常用于strcmp,memcmp
windows使用小端存储
- Title: 汇编重修
- Author: LinX
- Created at : 2026-02-01 13:41:39
- Updated at : 2026-02-01 13:49:26
- Link: https://redefine.ohevan.com/2026/02/01/汇编/
- License: This work is licensed under CC BY-NC-SA 4.0.