汇编语言
debug 是 DOS、Windows 都提供的实模式(8086 方式)程序的调试工具。
- R 命令查看、改变 CPU 寄存器的内容
- D 命令查看内存中的内容
- E 命令改写内存中的内容
- U 命令将内存中的机器指令翻译成汇编指令
- T 命令执行一条机器指令
- A 命令以汇编指令的格式在内存中写入一条机器指令
寄存器
| AH&AL = AX (accumulator):累加寄存器 |
| BH&BL = BX (base):基址寄存器 |
| CH&CL = CX (count):计数寄存器 |
| DH&DL = DX (data):数据寄存器 |
| SP (Stack Pointer):堆栈指针寄存器 |
| BP (Base Pointer):基址指针寄存器 |
| SI (Source Index):源变址寄存器 |
| DI (Destination Index):目的变址寄存器 |
| IP (Instruction Pointer):指令指针寄存器 |
| CS (Code Segment):代码段寄存器 |
| DS (Data Segment):数据段寄存器 |
| SS (Stack Segment):堆栈段寄存器 |
| ES (Extra Segment):附加段寄存器 |
| OF overflow flag 溢出标志 操作数超出机器能表示的范围表示溢出,溢出时为 1 |
| SF sign Flag 符号表示 记录运算结果的符号,结果负时为 1 |
| ZF zero flag 零标志 运算结果等于 0 时为 1,否则为 0 |
| CF carry flag 进位标志 最高有效位产生进位时为 1,否则为 0 |
| AF auxiliary carry flag 辅助进位标志,运算时,第 3 位向第 4 位产生进位时为 1,否则为 0 |
| PF parity flag 奇偶标志 运算结果操作数位为 1 的个数为偶数个数时为 1,否则为 0 |
| DF direcion flag 方向标志 用于串处理 DF = 1 时,每次操作后使 SI 和 DI 减小,DF = 0 时则增大 |
| IF interrupt flag 中断标志 IF = 1 时,允许 CPU 响应可屏蔽中断,否则关闭中断 |
| TF trap flag 陷阱标志 用于调试单步操作 |
mov 指令
| mov 寄存器、数据 比如:mov ax,8 |
| mov 寄存器、寄存器 比如:mov ax,bx |
| mov 寄存器、内存单元 比如:mov ax,[0] |
| mov 内存单元、寄存器 比如:mov [0],ax |
| mov 段寄存器、寄存器 比如:mov ds ax |
add 指令
sub 指令
mul 指令
- 两个相乘的数:两个相乘的数,要么都是 8 位,要么都是 16 位。如果是 8 位,一个默认放在 AL 中,另一个放在 8 位 reg 或内存字节单元中:如果是 16 位,一个默认放在 AX 中,另一个放在 16 位 reg 或内存字单元中。
- 结果:如果是 8 位乘法,结果默认放在 AX 中:如果是 16 位乘法,结果高位默认放在 DX 中存放,低位在 AX 中存放
| 计算 100 * 10 |
| mov al,64 |
| mov bl,A |
| mul bl |
| |
| 计算 100 * 10000 |
| mov ax,64 |
| mov bx,2710 |
| mul bx |
div 指令
- 除数:有 8 位和 16 位两种,在一个 reg 或内存单元中
- 被除数:默认放在 AX 或 DX 和 AX 中,如果除数为 8 位,被除数则为 16 位,默认在 AX 中存放:如果除数位16位,被除数则为 32 位,在 DX 和 AX 中存放,DX 存放高 16 位,AX 存放低 16 位
- 结果:如果除数为 8 位,则 AL 存储则 AL 存储除法操作的商,AH 存储除法操作的余数:如果除数为 16 位,则 AX 存储除法操作的商,DX 存储除法操作的余数
and 指令
| mov al,63 (01100011B) |
| and al,3B (00111011B) |
| 执行后 al = 23 (00100011B) |
or 指令
| mov al,63 (01100011B) |
| or al,3B (00111011B) |
| 执行后 al = 7B (01111011B) |
shl 和 shr 指令 (左移、右移)
| mov al,48 (01001000B) |
| shl al,1 |
| 执行后 al = 90 (10010000B) |
| |
| mov ax,F |
| shr ax,1 |
| 执行后 ax = 0007 |
rol、ror 循环左移、右移
rcl、rcr 带进位的循环左移、右移
inc 和 dec 指令(自增、自减)
nop(空指令)
xchg 指令(交换)
neg 指令(取补)
int 中断
段地址 * 16 + 偏移地址 = 物理地址
| 物理地址 段地址 偏移地址 |
| 21F60H 2000H 1F60H |
| 2100H 0F60H |
| 21F0H 0060H |
| 21F6H 0000H |
| 1F00H 2F60H |
ds 数据段寄存器
| mov bx,1000H |
| mov ds,bx |
| mov al,[0] -> ds:[0] |
CS、IP 寄存器 (代码段寄存器)
指示了 CPU 当前要读取指令的地址
jmp 指令(跳转指令)
| jmp 1000:3 跳转到 1000:3 |
| jmp bx 跳转到 1000:bx |
SS、SP 寄存器 (栈)
| push ax 把 ax 数据放入栈中 |
| pop ax 把 栈头 给 ax 并弹栈 |
[bx + idata]
可以用更为灵活的方式来指明内存单元:[bx + idata] 表示一个内存单元,它的偏移地址为(bx) + idata (bx 中的数值加上 idata)
SI、DI 寄存器
和bx功能相近,si 和 di 不能分成两个八 8 位寄存器来使用
| 下面的三组指令实现了相同的功能 |
| mov bx,0 |
| mov ax,[bx] |
| |
| mov si,0 |
| mov ax,[si] |
| |
| mov di,0 |
| mov ax,[di] |
| |
| 下面的三组指令实现了相同的功能 |
| mov bx,0 |
| mov ax,[bx + 123] |
| |
| mov si,0 |
| mov ax,[si + 123] |
| |
| mov di,0 |
| mov ax,[di + 123] |
[bx + si] 和 [bx + di]
灵活运用
| [idata] 用一个常量来表示地址,可用于直接定位一个内存单元 |
| [bx] 用一个变量来表示内存地址,可用于间接定位一个内存单元 |
| [bx + idata] 用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元 |
| [bx + si] 用两个变量表示地址 |
| [bx + si + idata] 用两个变量和一个常量表示地址 |
BP 寄存器
可以认为是 bx 的替代,bx 可以的指令 bp 基本都是可以的,但是有所不同
只要在 [...] 中使用寄存器 bp,而指令中没有显性地给出段地址,段地址就默认在 ss 中
寻址方式
| [idata] 直接寻址 |
| [bx] 寄存器间接寻址 |
| [bx + idata] 寄存器相对寻址 结构体:[bx].idata 数组:idata[bx] 二维数组:[bx][idata] |
| [bx + si] 基址变址寻址 二维数组:[bx][si] |
| [bx + si + idata] 相对基址变址寻址 用于表格中的数组项:[bx].idata[si] 二维数组:idata[bx][si] |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!