汇编语言
文章目录
基础知识
DEBUG工具
- R: 查看、改变CPU寄存器内容;
- D: 查看内存中的内容;
- U: 将内存中机器指令翻译成汇编指令;
- T: 执行一条机器指令;
- A: 以汇编指令的格式在内存中写入一条机器指令;
- E: 查看并改变内存中的内容;(数据)
寄存器
数据寄存器: AX, BX, CX, DX
- AX: (accumulator)累加器 //
- BX: (base)基址寄存器 //偏移地址,计算存储器地址时用作基址寄存器
- CX: (count)计数器 //做计数器,loop循环次数
- DX: (data)和AX组合使用 //和AX配合存放双字节数,存放端口地址
变址寄存器(指针): SP, BP, SI, DI
SP: 堆栈指针寄存器
BP: 基址指针寄存器 //和BX有类似作用,默认基地址为SS
SI: 源地址寄存器 //组合使用,来做偏移地址访问数据段
DI: 目的变址寄存器 //组合使用,来访问数据
专用寄存器: IP, SP, FLAGS
- IP: 指令指针寄存器
- SP: 堆栈指针寄存器
- FLAGS: 标志寄存器
段寄存器: CS, DS, SS, ES
- CS: 代码段
- DS: 数据段
- SS: 栈段
- ES: 附加段
应用
- 代码 CS:IP
- 数据 DS:SI ES:DI DS:1234H[DI][BX] = DS:[1234H + BX + DI]
- 栈 SS:SP SS:BP
指令
1. 数据传送指令
1.1 通用数据传送指令
mov (move) 传送
movsx (move with sign-extend) 带符号传送
movzx (move with zero-extend) 带0扩展传送
push (push onto the stack) 进栈
pop (pop from the stack) 出栈
pusha/pushad (push all registers) 所有寄存器进栈
popa/popad (pop all registers) 所有寄存器出栈
xchg (exchange) 交换
2.2 累加器专用传送指令
in (input) 输入
out (output) 输出
xlat (translate) 换码
2.3 地址传送指令
lea (load effective address) 有效地址送寄存器
lds (load DS with pointer) 指针送寄存器和DS
les (load ES with pointer) 指针送寄存器和ES
lfS (load FS with pointer) 指针送寄存器和FS
lgs (load GS with pointer) 指针送寄存器和GS
lss (load SS with pointer) 指针送寄存器和SS
2.4 标志寄存器传送指令
lahf (load AH with flags) 标志送AH
sahf (store AH into flags) AH送标志寄存器
pushf/pushfd (push the flags or eflags) 标志进栈
popf/popfd (pop the flags or eflags) 标志出栈
2.5 类型转换指令
cbw (convert byte to word) 将字节扩展为字
cwd (convert word to doubleword) 将字扩展为双字
cdq (convert doubleword to quadword) 将双字扩展为四字
bswap (byte swap) 字节交换
2. 算术指令
2.1 加法指令
add (add) 加法
adc (add with carry) 带进位加法
inc (increment) 加1
xadd (exchange and add) 交换并相加
2.2 减法指令
sub (subtract) 减法
sbb (subtract with borrow) 带借位减法
dec (decrement) 减1
neg (negate) 求补
cmp (compare) 比较
cmpxchg (compare and exchange) 比较并交换
cmpxchg (compare and exchange 8 byte) 比较并交换8字节
2.3 乘法指令
mul (unsigned multiple) 无符号数乘法
imul (signed multiple) 带符号数乘法
2.4 除法指令
div (unsighed divide) 无符号数除法
idiv (signed divide) 有符号数除法
2.5 十进制调整指令
aaa (ascii adjust for addition) 非压缩型BCD码加法调整指令
daa (decimal adjust for addition) 压缩型BCD加法调整指令
aas (ascii adjust for subtraction) 非压缩型BCD码减法调整指令
das (decimal adjust for subtraction) 压缩型BCD码减法调整指令
aam (ascii adjust for multiply) 非压缩型BCD码乘法调整指令
aad (ascii adjust for division) 非压缩型BCD码除法调整指令
3. 逻辑指令
3.1 逻辑运算指令
and (and) 逻辑与
or (or) 逻辑或
not (not) 逻辑非
xor (exclusive or) 异或
test (test) 测试
3.2 位测试并修改指令
bt (bit test) 位测试
bts (bit test and set) 位测试并置1
btr (bit test and reset) 位测试并置0
btc (bit test and complement) 位测试并变反
3.3 位扫描指令
bsf (bit scan forward) 正向位扫描
bsr (bit scan reverse) 反向位扫描
3.4 移位指令
shl (shift logical left) 逻辑左移
sal (shift arithmetic left) 算术左移
shr (shift logical right) 逻辑右移
sar (shift arithmetic right) 算术右移
rol (rotate left) 循环左移
ror (rotate right) 循环右移
rcl (rotate left through carry) 带进位循环左移
rcr (rotate right through carry) 带进位循环右移
shld (shift left double) 双精度左移
shrd (shift right double) 双精度右移
4. 串处理指令
movs (mov string) 串传送
cmps (compare string) 串比较
scans (scan string) 串扫描
lods (load from string) 从串取
stos (strore in to string) 存入串
ins (input from port to string) 串输入
outs (output string to port) 串输出
5.控制转移指令
5.1 无条件转移指令
jmp (jump) 跳转指令
5.2 条件跳转指令
jz/je (jump if zero, or equal)
jnz/jne (jump if not zero, or not equal)
js (jump if sign)
jns (jump if not sign)
jo (jump if overflow)
jno (jump if not overflow)
jp/jpe (jump if parity, or parity even)
jnp/jpo (jump if not parity, or parity odd)
jb/jnae/jc (jump if below, or not above of equal, or carry)
jnb/jae/jnc
jbe/jna (jump if below or equal, or not above)
jnbe/ja (jump if not below or equal, or above)
jl/jnge (jump if less, or not greater or equal)
jnl/jge (jump if not less, or greater or equal)
jle/jng (jump if less or equal, or not greater)
jnle/jg (jump if not less or equal, or greater)
jcxz (jump if CX register is zero)
jecxz (jump if ECX register is zero)
5.3 条件设置指令
5.4 循环指令
loop (loop) 循环
loopz/loope (loop while zero, or equal) 当为零或相等时循环指令
loopnz/loopne (loop while nonzero, or not equal) 当不为零或不相等时循环指令
5.5 子程序
call (call) 调用
ret (return) 返回
5.6 中断
int (interrupt) 中断
into (interrupt if overflow) 如溢出则中断
iret/iretd (return from interrupt) 从中断中返回
数据定义
db: define byte//定义字节型数据dw: define word//定义字型数据dd: double word//定义双字型数据dup: duplication//重复定义数据
例:
- db 3 dup (0) //定义3个字节型数据,初值为0
- db 3 dup (0, 1, 2) //定义9个字节型数据,初值为0, 1, 2, 0, 1, 2, 0, 1, 2
- db 3 dup (‘abc’, ‘ABC’) //定义18个字节型数据, 初值为’abcABCabcABCabcABC’
中断
发生中断
- 取得中断类型码
- 保存标志位寄存器中的值放入栈中(pushf)
- 将标志位寄存器中的第8位 TF(跟踪标志) 和 第9位 IF(中断允许标志) 设置为0
- push cs
- push ip
- cs = N * 4 + 2, ip = N * 4 (N为中断码)
中断返回
- pop ip
- pop cs
- popf
- 以上操作相当于 iret
中断码
很多初学汇编语言的同学可能会对INT 21H这条指令感到困惑,不知道是什么意思,下面就以一段简单的程序为大家讲解:
例如:需要键盘输入,并且回显。
AH的值需要查表取得,表在下面
指令:MOV AH,01
INT 21H
通过这样两条指令,输入的字符就会被存储在AL中。
表:DOS系统功能调INT 21H
| AH | 功能 | 调用参数 | 返回参数 |
|---|---|---|---|
| 00 | 程序终止(同INT 20H) | CS=程序段前缀 | |
| 01 | 键盘输入并回显 | AL=输入字符 | |
| 02 | 显示输出 | DL=输出字符 | |
| 03 | 异步通迅输入 | AL=输入数据 | |
| 04 | 异步通迅输出 | DL=输出数据 | |
| 05 | 打印机输出 | DL=输出字符 | |
| 06 | 直接控制台I/O | DL=FF(输入)DL=字符(输出) | AL=输入字符 |
| 07 | 键盘输入(无回显) | AL=输入字符 | |
| 08 | 键盘输入(无回显)检测Ctrl-Break | AL=输入字符 | |
| 09 | 显示字符串 | DS:DX=串地址’$'结束字符串 | |
| 0A | 键盘输入到缓冲区 | DS:DX=缓冲区首地址(DS:DX)=缓冲区最大字符数 | (DS:DX+1)=实际输入的字符数 |
| 0B | 检验键盘状态 | AL=00 有输入AL=FF 无输入 | |
| 0C | 清除输入缓冲区并请求指定的输入功能 | AL=输入功能号(1,6,7,8,A) | |
| 0D | 磁盘复位 | 清除文件缓冲区 | |
| 0E | 指定当前缺省的磁盘驱动器 | DL=驱动器号 0=A,1=B,… | AL=驱动器数 |
| 0F | 打开文件 | DS:DX=FCB首地址 | AL=00 文件找到AL=FF 文件未找到 |
| 10 | 关闭文件 | DS:DX=FCB首地址 | AL=00 目录修改成功AL=FF 目录中未找到文件 |
| 11 | 查找第一个目录项 | DS:DX=FCB首地址 | AL=00 找到AL=FF 未找到 |
| 12 | 查找下一个目录项 | DS:DX=FCB首地址(文件中带有*或?) | AL=00 找到AL=FF 未找到 |
| 13 | 删除文件 | DS:DX=FCB首地址 | AL=00 删除成功AL=FF 未找到 |
| 14 | 顺序读 | DS:DX=FCB首地址 | AL=00 读成功 =01 文件结束,记录中无数据 =02 DTA空间不够 =03 文件结束,记录不完整 |
| 15 | 顺序写 | DS:DX=FCB首地址 | AL=00 写成功 =01 盘满 =02 DTA空间不够 |
| 16 | 建文件 | DS:DX=FCB首地址 | AL=00 建立成功 =FF 无磁盘空间 |
| 17 | 文件改名 | DS:DX=FCB首地址(DS:DX+1)=旧文件名(DS:DX+17)=新文件名 | AL=00 成功AL=FF 未成功 |
| 19 | 取当前缺省磁盘驱动器 | AL=缺省的驱动器号 0=A,1=B,2=C,… | |
| 1A | 置DTA地址 | DS:DX=DTA地址 | |
| 1B | 取缺省驱动器FAT信息 | AL=每簇的扇区数DS:BX=FAT标识字节CX=物理扇区大小DX=缺省驱动器的簇数 | |
| 1C | 取任一驱动器FAT信息 | DL=驱动器号 | 同上 |
| 21 | 随机读 | DS:DX=FCB首地址 | AL=00 读成功 =01 文件结束 =02 缓冲区溢出 =03 缓冲区不满 |
| 22 | 随机写 | DS:DX=FCB首地址 | AL=00 写成功 =01 盘满 =02 缓冲区溢出 |
| 23 | 测定文件大小 | DS:DX=FCB首地址 | AL=00 成功(文件长度填入FCB)AL=FF 未找到 |
| 24 | 设置随机记录号 | DS:DX=FCB首地址 | |
| 25 | 设置中断向量 | DS:DX=中断向量AL=中断类型号 | |
| 26 | 建立程序段前缀 | DX=新的程序段前缀 | |
| 27 | 随机分块读 | DS:DX=FCB首地址CX=记录数 | AL=00 读成功 =01 文件结束 =02 缓冲区太小,传输结束 =03 缓冲区不满 |
| 28 | 随机分块写 | DS:DX=FCB首地址CX=记录数 | AL=00 写成功 =01 盘满 =02 缓冲区溢出 |
| 29 | 分析文件名 | ES:DI=FCB首地址DS:SI=ASCIIZ串AL=控制分析标志 | AL=00 标准文件 =01 多义文件 =02 非法盘符 |
| 2A | 取日期 | CX=年DH:DL=月:日(二进制) | |
| 2B | 设置日期 | CX:DH:DL=年:月:日 | AL=00 成功 =FF 无效 |
| 2C | 取时间 | CH:CL=时:分DH:DL=秒:1/100秒 | |
| 2D | 设置时间 | CH:CL=时:分DH:DL=秒:1/100秒 | AL=00 成功 =FF 无效 |
| 2E | 置磁盘自动读写标志 | AL=00 关闭标志AL=01 打开标志 | |
| 2F | 取磁盘缓冲区的首址 | ES:BX=缓冲区首址 | |
| 30 | 取DOS版本号 | AH=发行号,AL=版本 | |
| 31 | 结束并驻留 | AL=返回码DX=驻留区大小 | |
| 33 | Ctrl-Break检测 | AL=00 取状态 =01 置状态(DL)DL=00 关闭检测 =01 打开检测 | DL=00 关闭Ctrl-Break检测 =01 打开Ctrl-Break检测 |
| 35 | 取中断向量 | AL=中断类型 | ES:BX=中断向量 |
| 36 | 取空闲磁盘空间 | DL=驱动器号 0=缺省,1=A,2=B,… | 成功:AX=每簇扇区数 BX=有效簇数 CX=每扇区字节数 DX=总簇数失败:AX=FFFF |
| 38 | 置/取国家信息 | DS:DX=信息区首地址 | BX=国家码(国际电话前缀码)AX=错误码 |
| 39 | 建立子目录(MKDIR) | DS:DX=ASCIIZ串地址 | AX=错误码 |
| 3A | 删除子目录(RMDIR) | DS:DX=ASCIIZ串地址 | AX=错误码 |
| 3B | 改变当前目录(CHDIR) | DS:DX=ASCIIZ串地址 | AX=错误码 |
| 3C | 建立文件 | DS:DX=ASCIIZ串地址CX=文件属性 | 成功:AX=文件代号错误:AX=错误码 |
| 3D | 打开文件 | DS:DX=ASCIIZ串地址AL=0 读 =1 写 =3 读/写 | 成功:AX=文件代号错误:AX=错误码 |
| 3E | 关闭文件 | BX=文件代号 | 失败:AX=错误码 |
| 3F | 读文件或设备 | DS:DX=数据缓冲区地址BX=文件代号CX=读取的字节数 | 读成功: AX=实际读入的字节数 AX=0 已到文件尾读出错:AX=错误码 |
| 40 | 写文件或设备 | DS:DX=数据缓冲区地址BX=文件代号CX=写入的字节数 | 写成功: AX=实际写入的字节数写出错:AX=错误码 |
| 41 | 删除文件 | DS:DX=ASCIIZ串地址 | 成功:AX=00出错:AX=错误码(2,5) |
| 42 | 移动文件指针 | BX=文件代号CX:DX=位移量AL=移动方式(0:从文件头绝对位移,1:从当前位置相对移动,2:从文件尾绝对位移) | 成功:DX:AX=新文件指针位置出错:AX=错误码 |
| 43 | 置/取文件属性 | DS:DX=ASCIIZ串地址AL=0 取文件属性AL=1 置文件属性CX=文件属性 | 成功:CX=文件属性失败:CX=错误码 |
| 44 | 设备文件I/O控制 | BX=文件代号AL=0 取状态 =1 置状态DX =2 读数据 =3 写数据 =6 取输入状态 =7 取输出状态 | DX=设备信息 |
| 45 | 复制文件代号 | BX=文件代号1 | 成功:AX=文件代号2失败:AX=错误码 |
| 46 | 人工复制文件代号 | BX=文件代号1CX=文件代号2 | 失败:AX=错误码 |
| 47 | 取当前目录路径名 | DL=驱动器号DS:SI=ASCIIZ串地址 | (DS:SI)=ASCIIZ串失败:AX=出错码 |
| 48 | 分配内存空间 | BX=申请内存容量 | 成功:AX=分配内存首地失败:BX=最大可用内存 |
| 49 | 释放内容空间 | ES=内存起始段地址 | 失败:AX=错误码 |
| 4A | 调整已分配的存储块 | ES=原内存起始地址BX=再申请的容量 | 失败:BX=最大可用空间 AX=错误码 |
| 4B | 装配/执行程序 | DS:DX=ASCIIZ串地址ES:BX=参数区首地址AL=0 装入执行AL=3 装入不执行 | 失败:AX=错误码 |
| 4C | 带返回码结束 | AL=返回码 | |
| 4D | 取返回代码 | AX=返回代码 | |
| 4E | 查找第一个匹配文件 | DS:DX=ASCIIZ串地址CX=属性 | AX=出错代码(02,18) |
| 4F | 查找下一个匹配文件 | DS:DX=ASCIIZ串地址(文件名中带有?或*) | AX=出错代码(18) |
| 54 | 取盘自动读写标志 | AL=当前标志值 | |
| 56 | 文件改名 | DS:DX=ASCIIZ串(旧)ES:DI=ASCIIZ串(新) | AX=出错码(03,05,17) |
| 57 | 置/取文件日期和时间 | BX=文件代号AL=0 读取AL=1 设置(DX:CX) | DX:CX=日期和时间失败:AX=错误码 |
| 58 | 取/置分配策略码 | AL=0 取码AL=1 置码(BX) | 成功:AX=策略码失败:AX=错误码 |
| 59 | 取扩充错误码 | AX=扩充错误码BH=错误类型BL=建议的操作CH=错误场所 | |
| 5A | 建立临时文件 | CX=文件属性DS:DX=ASCIIZ串地址 | 成功:AX=文件代号失败:AX=错误码 |
| 5B | 建立新文件 | CX=文件属性DS:DX=ASCIIZ串地址 | 成功:AX=文件代号失败:AX=错误码 |
| 5C | 控制文件存取 | AL=00封锁 =01开启BX=文件代号CX:DX=文件位移SI:DI=文件长度 | 失败:AX=错误码 |
| 62 | 取程序段前缀 | BX=PSP地址 |
原码、补码、反码
正数
[真值]D = [原码]B = [反码]B = [补码]B
负数
第一位为符号位
取反、加一
[真值]D = [原码]B --------------->[反码]B -------> [补码]B
减一、取反
[真值]D = [原码]B <---------------[反码]B <------- [补码]B
特殊
因为 0 = -0 [0000 0000] = [1000 0000]
所以规定 1000 0000表示-128
所以有符号数的取值范围是 -128 ~ 127
注意
汇编语言中的指令中的数据代表的是补码
寻址方式
- 立即寻址方式
- 寄存器寻址方式
- 直接寻址方式
- 寄存器间接寻址方式
- 寄存器相对寻址方式
- 基址变址寻址方式
- 相对基址变址寻址方式
标志位的状态
| OF | DF | IF | TF | SF | ZF | AF | PF | CF | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 标志名 | 标志为1 | 标志为0 |
|---|---|---|
| OF (溢出) | OV (是) | NV (否) |
| DF (方向) | DN (减量) | UP (增量) |
| IF (中断) | EI (允许) | DI (关闭) |
| SF (符号) | NG (为负) | PL (为正) |
| ZF (零) | ZR (是) | NZ (否) |
| AF (辅助进位) | AC (是) | NA (否) |
| PF (奇偶) | PE (偶) | PO (奇) |
| CF (进位) | CY (是) | NC (否) |
状态标志位
- 进位标志CF(Carry Flag)
- 奇偶标志PF(Parity Flag)
- 辅助进位标志AF(Auxiliary Carry Flag)
- 零标志ZF(Zero Flag)
- 符号标志SF(Sign Flag)
- 溢出标志OF(Overflow Flag)
控制标志位
- 追踪标志TF(Trap Flag)
- 中断允许标志IF(Interrupt-enable Flag)
- 方向标志DF(Direction Flag)
MASM5.0组成
系统组成:
- 宏汇编程序masm.exe,将.ASM文件汇编成目标文件.OBJ
- 连接程序link.exe,将.OBJ连接成可执行文件.EXE
- 库管理程序lib.exe,用于创建和管理子程序库
- 索引程序cref.exe,用于出售交叉索引文件.REF
- 编辑工具edit.exe,用于编辑源程序文件.asm
各文件含义:
- .asm 源程序文件,汇编语言源程序文件,用文本编辑工具产生的。
- .obj 目标文件,在汇编时,利用MASM.EXE 对.asm源程序汇编时生成的。
- .lst 列表文件,在汇编时,利用MASM.EXE 对源程序.asm汇编时,通过选择生成的。
- .crf交叉索引文件。在汇编时,利用MASM.EXE 对源程序.asm汇编时通过选择生成的。
- .map 列表映像文件,在对目标文件(.obj)连接过程中,选择生成的。
- .exe 执行文件,在对目标文件(.obj)连接过程中生成的。
- .ref 索引文件,利用汇编系统中交叉索引程序:CREF.EXE 将.CRF 转换成.REF文件,而.REF文件可用文本编辑工具打开阅读。
- .lib 汇编语言的程序库文件,利用子程序库管理程序LIB.EXE创建的,供程序调用。
上机步骤:
- 编辑源程序 edit 源程序名.asm
- 对源程序汇编生成目标文件 masm 程序名
- 对目标文件进行连接生成可执行文件 link 程序名
- 运行文件 程序名
代码
输入字符串并在屏幕输出字符串–改进版
;输入字符串并在屏幕输出字符串--改进版
datas segment
str db "please input a string:$"
buf db 200 ;buf表示最大长度,buf+1表示已经输入的长度
db ?
db 200 dup(?)
crlf db 0ah, 0dh, '$'
datas ends
stacks segment stack
db 200 dup(?)
stacks ends
codes segment
assume cs:codes, ds:datas, ss:stacks
start: mov ax, datas
mov ds, ax
lea dx, str
mov ah, 9
int 21h
mov ah, 10
lea dx, buf
int 21h
lea dx, crlf
mov ah, 9
int 21h
mov bl, buf+1
mov bh, 0
lea si, buf+2
mov byte ptr [bx][si], '$'
mov dx, si
mov ah, 9
int 21h
mov ax, 4c00h
int 21h
codes ends
end start
A存放数据,B存放数据,A+B存到C
mov dx, word ptr A
mov ax, word ptr A+2
add dx, word ptr B
add ax, word ptr B+2
mov word ptr C, dx
mov word ptr C+2, ax
在屏幕上显示 "I am a student."
datas segment
buf db "I am a student.$"
datas ends
codes segment
assume ds:datas, cs:codes
start: mov ax, datas
mov ds, ax
lea dx, buf
mov ah, 9
int 21h
mov ax, 4c00h
int 21h
codes ends
end start
对累加器AX清零
mov ax, 0
and ax, 0
xor ax, ax
sub ax, ax
注意
小技巧
- 数字+30H=数字字符的ASCII值
- 大写字符ASCII值+20H=小写字符的ASCII值
- 小写字符ASCII值-20H=大写字符的ASCII值
常见符号的ASCii码
- 换行符LF 0ah = 10
- 回车符CR 0dh = 13
- space 20h = 32
- ‘0’ 30h = 48
- ‘A’ 41h = 65
- ‘a’ 61h = 97
寄存器赋值
报错
mov cs,1000H
mov ds,1000H
不报错
mov cs,ax
mov ds,bx
结论段地址寄存器不支持用数据直接赋值
本文详细介绍了汇编语言的基础知识,包括DEBUG工具的使用、寄存器的作用及各类指令的功能,同时还提供了数据定义、中断处理等内容。适用于初学者入门及高级用户深入学习。
1192

被折叠的 条评论
为什么被折叠?



