寄存器名称意义
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 陷阱标志 用于调试单步操作
详细介绍
bx
# bx 可以特别用于记录偏移地址(ax,cx等一般寄存器做不到)
mov ax,[bx]
# 将 ds:bx 处的数据赋给 ax
mov ax,[bx+1]
# 等价写法
mov ax,[bx].1
mov ax,1[bx]
mov ax,[bx][1]
si, di
# 与 bx 功能相近,区别在于不能被拆为两个 8bits 使用,而 bx 可以拆成 bh 和 bl
mov cx,[si]
mov cx,[di]
mov cx,[bx+si]
mov cx,[bx+di]
mov cx,[bx+si+1]
mov cx,[bx+di+1]
mov cx,[bx+si+di+1] # 报错,si 和 di 无法同时出现
bp
# 与 bx 功能相近,区别在于没有显性给定段地址的时候在 ss 中取段地址,bx,si,di 是在 ds 中取的段地址,且 bx, bp 不能同时出现
mov cx,[bp]
mov cx,[bp+si]
mov cx,[bp+di+1]
flag
zf
# 零标志,结果为 0 则为 0 (显示 ZR),非 0 则为 1 (显示 NZ)
# zero; not zero
pf
# 奇偶标志,运算结果操作数位为 1 的个数为偶数个时为 1 (显示为 PE), 否则为 0 (显示为 PO)
# odd; even
sf
# 符号标志,运算结果为负则 1 (显示为 NG),非负则 0 (显示为 PL)
# negative; plus
cf
# 进位标志,记录从最高有效位向更高位的进位值(NC,CY)
# no carry; carry
of
# 溢出标志(OV,NV)
# overflow; not overflow
debug 基础指令
- # Read?
-r # 查看寄存器内容
-r ax # 修改指定寄存器的值 - # Dump
-d 0000:0000 # 查看内存内容;段地址:偏移地址
-d 0:0 f # 输出指定数字(hex)个信息 - # Enter
-e 0:0 11 22 33 44 # 从0:0开始修改信息
-e 0:0 # 从0:0开始修改信息,但是会自动跳出来要修改的内容,空格继续,回车结束 - # Assemble
-a 073F:0100 # 从指定位置(寄存器)开始写入汇编代码 - # trace
-t # 执行指向 CS:IP 的代码
# 成功执行后自动跳到下一句 - # Unassemble
-u 073F:0100 # 机器码翻译成汇编码
运算指令
赋值 mov
mov
- # 寄存器有 ax, bx, cx (4位16进制,即16位2进制)等等,可用 ah 表示变量 ax 的高8位,al 表示变量 ax 的低8位
- mov ax,8 # 将数据 8 移动(覆盖)到寄存器 ax 的位置
- mov ax,bx # 将寄存器 bx 中的内容移动(覆盖)到寄存器 ax 的位置
- mov bh,al #将 ax 的低8位移动(覆盖)到 bx 的高8位位置
- mov ax,[0]
- mov [0],ax
- mov ds,ax
四则运算 add, sub, mul, div
add
- add ax,3 # ax = ax + 3(hex)
- add ax,bx # ax = ax + bx, 越界(>FFFF)高位舍弃
add al,bx # al = al + bx, al若越界(>FF)高位舍弃,不会进位到 ah 中 - add ax,[0]
- add [0],ax
sub
- # 与 add 类似
sub ax,3 # ax = ax – 3(hex) - # 越界; bx = 000f
sub bx,10
# 可以看作 bx 借位变成 1000f 再减 10 得到 ffff
# 补码 = 反码 + 1
# 也可以转换成补码:-0010 等价于 +fff0,故得到 ffff
mul
- # mul 乘法只接受一个参数,且只能 8bits x 8bits 或者 16bits x 16bits
- # 8bits 相乘,一个参数默认在 al 中,结果默认放在 ax 中
mul 10 # ax = al * 10(hex) - # 16bits 相乘,结果高位默认放在 dx 中,低位放在 ax 中
mov ax,64
mov bx,2710
mul bx
# 64h x 2710h = F4240h
# 结果:(ax)=4240h, (dx)=000Fh
div
- # div 只接受除数参数,被除数默认在 ax (除数8bits,被除数16bits) 或 dx 和 ax (除数16bits,被除数32bits,dx高位,ax低位) 中
# 结果:
# 除数 8bits,则 al 存储商,ah 存储余数
# 除数 16bits,则 ax 存储商, dx 存储余数
mov ax,2710
mov bl,64
div bl
# 结果:ax = 0064 - mov dx,f
mov ax,4241
mov bx,2710
div bx
# 结果:ax = 0064, dx = 0001
逻辑运算 and, or
- mov al,63 # 01100011B
and al,3B # 00111011B
# 结果:al = 23 # 00100011B
# 注意:debug 模式不支持 “mov al,01100011B” 这种写法 - # or 同理
左移右移 shl, shr
- mov al,48
shl al,1
# 结果:ax = 0090 - mov al,90
shr al,1
# 结果:ax = 0048 - # rol 循环左移
# ror 循环右移 - # rcl 算术左移
# rcr 算术右移
自增自减 inc, dec
- mov ax,3
inc ax # ax++
dec ax # ax–
空指令 nop
- nop # 占一个字节
交换 xchg
- xchg ax,bx
# 交换 ax, bx 的值
取反 neg
- mov ax,2
neg ax
# 结果:ax = fffe
# 本质是取反后 +1
跳转 jmp
- # 初始状态 CS=2000H IP=0000H
mov ax,6622 # 3字
jmp 1000:3 # 5字
mov cx,ax # 2字
# 在 1000:0000 中存有如下代码
mov ax,0123 # 3字
mov ax,0000 # 3字
mov bx,ax # 2字
jmp bx # 2字
# 分析:ax=6622, 跳转到 1000:0003, ax=0000, bx=ax=0000, 跳转到 1000:0000 (单个参数只改变 IP 值), ax=0123, ax=0000, 进入死循环
# 直接给 CS IP 赋值会报错,故使用 jmp 语句
入栈,出栈 push, pop
# SS:SP 指向栈顶元素
-r ss 1000
-r sp 0010
# 设置栈顶为 1000:0010, 这样第一次入栈位置就在 1000:000F (栈底高位,栈顶低位)
mov ax,0123
push ax
# 结果:1000F 存放 01, 1000E 存放23
mov bx,2266
push bx
# 结果:1000D 存放 22,1000C 存放66
mov cx,1122
push cx
# 同理
# 1000A: 22
# 1000B: 11
# 1000C: 66
# 1000D: 22
# 1000E: 23
# 1000F: 01
pop ax
# 1000A 弹出赋给 ax 低位 al,1000B 弹出赋给 ax 高位 ah
# ax = 1122
pop bx
pop cx
# 结果:ax = 1122, bx = 2266, cx = 0123
push [0]
# 将 DS:0000 处数据压入栈
其他运算
adc
# add -> adc carry 带进位加法
# adc ax,bx 即 ax = ax + bx + CF
# 若在 add 中出现进位或在 sub 中出现借位则会使 CF 变为 1,否则为 0
mov ax,2
mov bx,1
sub bx,ax
adc ax,1
# 结果:ax = 4
# 该命令的意义:加法可以分为两步进行:1. 低位相加 2. 高位相加再加上地位相加产生的进位值
sbb
# 类似 adc, 借位减法
# sbb ax,bx 即 ax = ax - bx - CF
cmp
# 不保存结果的减法指令,会对其他受影响寄存器产生改变,但是不记录减法的结果
# 与一些跳转指令结合形成 if ... then ... 的效果
# je equal zf = 1
# jne not equal zf = 0
# jb below cf = 1
# jnb not below cf = 0
# ja above cf = 0 & zf = 0
# jna not above cf = 1 | zf = 1
中断
int 0
# 除零错误导致 int 0 中断
mov bl,0
mov ax,123
div bl
# 结果:CS:IP 跳转到 F000:1060
# 与命令 int 0 执行后效果相同
# int 为 interrupt 的缩写
int 9
int 13
int 21
mov ax,4c00
int 21
# 安全退出
地址
段地址 x 16 + 偏移地址 = 物理地址
-d 2000:1F60
-d 2100:0F60
# 两个命令查看到的内容是一样的
DS 寄存器:段寄存器,存储段地址
-e 2000:1F60
# 写入几个数
2000:1F60 00.12 00.34 00.56 00.78 00.9A 00.BC
-r DS 21F0
# 将段寄存器内容修改为 21F0
mov ax,[60]
# 段地址在 DS 中,中括号内表示偏移地址;将结果赋给 ax
# 即从 21F0:0060 开始将数据赋给 ax
# 结果:ax = 3412
# 12 低位赋给 ax 低位,34 高位赋给 ax 高位
DS 不能直接被赋值,但可以通过其他寄存器赋值
mov ds,1000 # 报错
mov ax,1000
mov dx,ax # 可行