⚡ 亲手编写基于王爽老师《汇编语言》的300个汇编程序例程
In this folder, I recorded notes and codes for learning assembly language in the summer vacation of 2020. :P
注:部分代码及练习基于王爽《汇编语言》第三版,具体题目及要求请见书中
笔记请详见:
文件夹编号说明:
其中,为了避免文件夹命名及编号混乱:【预留空位】指的是为以后复习或者相关新项目所预留出来的编号。
编号 | 说明 |
---|---|
1 - 2 | 基础 |
3 - 17 | 基于loop指令的代码及练习 |
18 - 20 | 【预留空位】loop指令预留空位 |
21 - 27 | and和or指令 |
28 - 30 | 【预留空位】and和or指令 |
31 - 32 | byte ptr 字节型数据 和 word ptr 字型数据 |
33 - 35 | 【预留空位】 |
36 - 40 | div除法操作 |
41 - 45 | div指令【预留空位】 |
46 - 47 | 寻址方式在结构化数据访问中的应用 |
48 - 50 | 【预留空位】 |
51 | offset操作符 |
52 - 55 | 【预留空位】 |
56 - 65 | JMP指令 |
66 | jcxz条件转移指令 |
67 - 69 | 【预留空位】 |
70 | LOOP循环指令 |
71 - 74 | 【预留空位】 |
74 - 77 | 向屏幕彩色输出【实验9】 |
78 - 80 | 【预留空位】 |
82 - 83 | ret、retf指令 |
84 - 85 | 【预留空位】 |
86 - 90 | 几种call的简介 |
91 - 98 | call指令与ret的联合应用 |
99 - 100 | 【预留空位】 |
101 - 102 | mul乘法指令 |
103 - 106 | 利用子程序的对字符串进行大小写转换 |
106 - 110 | 【预留空位】 |
111 - 117 | 设计一简化版(整理内存段中的数据、进行乘除法、将数值转化为对应的ASCII码) |
118 - 119 | 【预留空位】 |
120 - 126 | 初步显示字符串 |
127 - 129 | 【预留空位】 |
130 - 132 | adc指令 |
136 | sbb指令 |
140 - 146 | cmp条件判断指令 |
150 - 151 | rep movsb、cld/std实现数据正向/逆向传送 |
160 | 以0结尾的字符串中小写字母转大写【综合运用】 |
170 | 错误信息写入中断向量表【内中断】 |
180 - 188 | 中断例程的运用 |
199 | 使用加法和位移指令计算(ax)=(ax)x10 |
200 - 202 | 端口的初步造作 |
205 | 以“年-月-日 时;分;秒”的格式,显示当前时间 |
220 - 224 | 键盘中断例程 |
240 - 248 | 通过标号定位数据、直接定址表 |
260 - 261 | 接受键盘输入 |
300 - 310 | C/C++ 下汇编测试 |
500 | 高级汇编例程 |
英文名 | 寄存器 | 类型 | 具体名称 | 常用关联 |
---|---|---|---|---|
Accumulator | ax | 数据寄存器 | 累加寄存器/累加器 | div除法指令和mul乘法指令会调用;端口的输入输出只能用ax、al存放 |
Base | bx | 数据寄存器 | 基地址寄存器 | 经常与ds, es连用;[bx] 默认调用ds:[bx] |
Count | cx | 数据寄存器 | 计数器寄存器 | 储存循环次数,loop、jcxz指令会调用cx |
Data | dx | 数据寄存器 | 数据寄存器 | 常用来储存数据 |
Stack Pointer | sp | 指针寄存器 | 堆栈指针寄存器 | 存放栈顶的偏移地址 |
Base Pointer | bp | 指针寄存器 | 基指针寄存器 | 默认与ss相关联,比如 [bp] 默认调用 ss:[bp] |
Source Index | si | 变址寄存器 | 源地址寄存器 | 常用于 ds:[si],存放偏移地址,数据从哪里来 |
Destination Index | di | 变址寄存器 | 目的地址寄存器 | 常用于 es:[di],存放偏移地址,数据到哪里去 |
Data Segment | ds | 数据段寄存器 | 常用于 ds:[si],存放段地址,数据从哪里来 | |
Extra Segment | es | 附加段寄存器 | 常用于 es:[di],存放段地址,数据到哪里来 | |
Stack Segment | ss | 堆栈段寄存器 | 存放栈的段地址 | |
Code Segment | cs | 代码段寄存器 | 存放执行指令的段地址 | |
Instruction Pointer | ip | 控制寄存器 | 指令指针寄存器 | 存放执行指令的偏移地址 |
Flag | FLAG | 控制寄存器 | 标志寄存器 | 请见下一表格《标志寄存器 PSW》 |
PWD - program status word 程序状态字
- Flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息
- mov、push、pop 对标志位寄存器没有影响
- 溢出:运算结果超出了机器所能表达的范围,把符号位给顶了
- 注意CF和OF的区别
- 16进制数大于80H时既可以看作是有符号数,也可以看作为无符号,这取决于将标志位视为什么(对于8位寄存器)
标志寄存器在Debug中的表示:
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0000 ES=0000 SS=0000 CS=0000 IP=0000 NV UP EI PL NZ NA PO NC
↑ ↑ ↑ ↑ ↑ ↑
OF DF SP ZF PF CF
位 | 中文名称 | 标志寄存器 | 真值 1 | 假值 0 | 首字母含义 | 操作的编码 | 说明 |
---|---|---|---|---|---|---|---|
编程小技巧: 将ds与si配合使用 将es与di配合使用 <--- 虽然es和si可以配合使用,但是介于后面涉及的课程及指令,不建议使用 ds:di,、es:si !!
在对程序分段时,如果遇到寄存器冲突,可以先将冲突的寄存器push到栈中,需要时再pop出来
如果合理的使用db, dw, dd ==> 看操作的寄存器,比如:操作的寄存器为16位,则应该用dw
如果参数过多,要处理的数据使用较多的寄存器,那么可以先将数据进行结构化处理再进行编写代码,这样可以更好的处理数据
将字符串显示在屏幕上(B800H)时,一定要注意将存放属性的高位字节写入数据,否则会造成无法显示 将字符串显示在屏幕上(B800H)时,先输出余数,在对ax中的商是否为零进行判断,否则会造成以零为结尾的数值无法显示
将int型数值转换为string字符串时,在进行除10取余时,每显示完一个字符,记得将储存高位字节的dx清零
在编写子程序时,可在程序开头处将程序中用到的寄存器进行push,在ret前再进行pop,这样就不用考虑是否会影响到程序外的寄存器(注意push和pop的顺序)