读书笔记——汇编语言 第四版 王爽著
<p>同步发布于</p><p>http://mp.weixin.qq.com/s?__biz=Mzg5OTU1NDEyOA==&mid=2247483683&idx=1&sn=5b45dddcc8ddc5cb24c0b4e1be13cbd9&chksm=c050cf1cf727460a8f11d4d61b245fdbd8cfb5d2ddacc99813f92acd21ee9086afd79ae364e9#rd</p>
<p>获取相关资源, 请在文章末尾扫描微信公众号</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"> 汇编语言 第4版 王爽 著
(学习笔记)
第一章基础知识
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.汇编指令是机器指令便于记忆的书写格式
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.寄存器是CPU中存储数据的器件
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.编译器将汇编指令转换为机器指令
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.汇编指令有对应的机器码
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.伪指令由编译器执行, 没有对应的机器码
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.符号由编译器识别, 没有对应的机器码
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.存储器被划分为多个存储单元, 存储单元从零开始顺序编号(地址)
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.一根根导线集合为总线, 分为地址, 控制, 数据总线
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.N根线可以说总线宽度为N
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.8088CPU数据总线宽度为8, 8086CPU数据总线宽度为16
</span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">.CPU通过总线向接口卡发送命令, 间接控制外设工作
</span><span style="color: rgba(128, 0, 128, 1)">11</span><span style="color: rgba(0, 0, 0, 1)">.CPU将系统中各类存储器(一段地址空间)看作一个逻辑存储器(内存地址空间)
</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">.地址0x0000~0x7FFF为主随机存储器的地址空间
</span><span style="color: rgba(128, 0, 128, 1)">13</span><span style="color: rgba(0, 0, 0, 1)">.地址0x8000~0x9FFF为显存的地址空间
</span><span style="color: rgba(128, 0, 128, 1)">14</span><span style="color: rgba(0, 0, 0, 1)">.地址0xA000~0xFFFF为各个ROM的地址空间
第二章寄存器
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.典型的CPU由运算器,控制器,寄存器构成依靠内部总线相连
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.通用寄存器X可分为H和L两个独立的寄存器使用(Word = 0x02 * Byte)
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.在数据运算或传输时, 指令操作的两个对象的位数应该一致
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.物理地址 = 基础地址(段地址 * 0x10) + 偏移地址, 将地址连续起始地址为16的倍数的一组内存单元定义为段
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.一个X进制的数左移0x01位=乘以X
</span><span style="color: rgba(128, 0, 128, 1)">5</span>.在8086机中, <span style="color: rgba(0, 128, 128, 1)">任意时刻CPU将cs:</span><span style="color: rgba(0, 0, 0, 1)">ip指向的内容当做指令执行
</span><span style="color: rgba(128, 0, 128, 1)">6</span>.<span style="color: rgba(0, 128, 128, 1)">从cs:</span><span style="color: rgba(0, 0, 0, 1)">ip指向的内存读取一条指令(送入指令缓冲器)后, ip中的值自动增加该指令的长度, 执行控制器执行该指令
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.mov指令被称为传送指令
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.能够改变cs,ip内容的指令被统称为转移指令
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.8086CPU工作过程
a. </span><span style="color: rgba(0, 128, 128, 1)">从cs:</span><span style="color: rgba(0, 0, 0, 1)">ip指向的内存单元读取指令, 读取的指令进入指令缓冲器
b. (IP) = (IP) + 读取的指令长度, 指向下一条指令
c. 执行指令
d. 转到a, 重复该过程
</span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">.DEBUG指令(常用)
</span><span style="color: rgba(0, 128, 128, 1)">A:</span> 以汇编指令的格式在内存中写入一条机器指令(A <span style="color: rgba(0, 128, 128, 1)">段地址:</span><span style="color: rgba(0, 0, 0, 1)">偏移地址)
</span><span style="color: rgba(0, 128, 128, 1)">D:</span> 查看内存(D <span style="color: rgba(0, 128, 128, 1)">段地址:</span><span style="color: rgba(0, 0, 0, 1)">起始偏移地址 [结束偏移地址])
</span><span style="color: rgba(0, 128, 128, 1)">E:</span> 向内存中写入机器码(E <span style="color: rgba(0, 128, 128, 1)">段地址:</span><span style="color: rgba(0, 0, 0, 1)">偏移地址 数据 [数据 [...]])
</span><span style="color: rgba(0, 128, 128, 1)">G:</span><span style="color: rgba(0, 0, 0, 1)"> 程序直接运行到指定地址位置(G 偏移地址)
</span><span style="color: rgba(0, 128, 128, 1)">R:</span><span style="color: rgba(0, 0, 0, 1)"> 查看, 改变寄存器(R 寄存器)
</span><span style="color: rgba(0, 128, 128, 1)">T:</span><span style="color: rgba(0, 0, 0, 1)"> 执行一条机器指令
</span><span style="color: rgba(0, 128, 128, 1)">U:</span> 查看内存指令翻译的汇编指令(U <span style="color: rgba(0, 128, 128, 1)">段地址:</span><span style="color: rgba(0, 0, 0, 1)">偏移地址)
</span><span style="color: rgba(0, 128, 128, 1)">P:</span> 当遇到 <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 21H 正常结束指令时使用P指令
当遇到 loop 指令时, Debug会自动重复执行循环中的指令直到(CX)=0x00为止
第三章寄存器(内存访问)
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.存放一个字型数据(0x10 Bit)的内存单元为字单元
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.8086CPU自动取ds的数据作为内存单元的段地址
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.8086CPU不支持将数据直接送入段寄存器
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.8086CPU的内存传送指令push(入栈)和pop(出栈)操作都是以字为单位进行的
</span><span style="color: rgba(128, 0, 128, 1)">4</span>.<span style="color: rgba(0, 128, 128, 1)">任意时刻ss:</span><span style="color: rgba(0, 0, 0, 1)">sp指向栈顶元素
</span><span style="color: rgba(128, 0, 128, 1)">5</span>.<span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)">(入栈)执行步骤(栈顶从高地址向低地址方向移动)
a. (SP) = (SP) - 0x02, </span><span style="color: rgba(0, 128, 128, 1)">ss:</span><span style="color: rgba(0, 0, 0, 1)">sp指向当前栈顶前面的单元作为新的栈顶
b. </span><span style="color: rgba(0, 128, 128, 1)">将内存数据送入ss:</span>sp指向的内存单元, <span style="color: rgba(0, 128, 128, 1)">此时ss:</span><span style="color: rgba(0, 0, 0, 1)">sp指向新栈顶
</span><span style="color: rgba(128, 0, 128, 1)">6</span>.<span style="color: rgba(0, 128, 128, 1)">栈空ss:</span><span style="color: rgba(0, 0, 0, 1)">sp指向栈空间最高地址单元的后一个单元(栈最底部的字单元的偏移地址 + 0x02)
</span><span style="color: rgba(128, 0, 128, 1)">7</span>.<span style="color: rgba(0, 0, 255, 1)">pop</span><span style="color: rgba(0, 0, 0, 1)">(出栈)执行步骤(栈顶从低地址向高地址方向移动)
a. </span><span style="color: rgba(0, 128, 128, 1)">将SS:</span><span style="color: rgba(0, 0, 0, 1)">SP指向的内存单元处的数据读出(已不在栈中)
b. (SP) = (SP) + 0x02, </span><span style="color: rgba(0, 128, 128, 1)">ss:</span><span style="color: rgba(0, 0, 0, 1)">sp指向当前栈顶后面的单元, 以当前栈顶后面的单元为新的栈顶
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.栈操作要注意防止越界
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.Debug的T命令在执行修改寄存器ss的指令时, 下一条指令也紧接着被执行
第四章第一个程序
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.伪指令 段(segment/ends)成对使用的伪指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> 段名 segment <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">段开始</span>
段名 ends <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">段结束</span>
<span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> msCode segment
msCode ends
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.伪指令 假设(assume)将段寄存器和某一具体的段相联系
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> assume <span style="color: rgba(0, 128, 128, 1)">寄存器:</span><span style="color: rgba(0, 0, 0, 1)">段名
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> assume <span style="color: rgba(0, 128, 128, 1)">cs:</span><span style="color: rgba(0, 0, 0, 1)">msCode
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.伪指令 程序结束(end)与程序入口
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> end [<span style="color: rgba(0, 0, 255, 1)">enter</span><span style="color: rgba(0, 0, 0, 1)">-flag]
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> end sMain
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.程序返回指令(Debug按 P 命令执行正常结束)
</span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ax, 4c00H
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 21H
</span><span style="color: rgba(128, 0, 128, 1)">4</span>.Debug将程序加载入内存(=<span style="color: rgba(0, 128, 128, 1)">sa:</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)区后, cx中存放程序的长度
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.内存区前0x100个字节为程序段前缀(PSP)头字节为{0xCD 0x20}
</span><span style="color: rgba(128, 0, 128, 1)">6</span>.ds(=<span style="color: rgba(0, 128, 128, 1)">sa:</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)中存放程序所在内存区(含PSP)的段地址
</span><span style="color: rgba(128, 0, 128, 1)">7</span>.则程序的地址为(CS) = (DS + 10H):(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
第五章和loop指令
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.约定符号()表示一个寄存器或内存单元的内容, 符号idata表示常量
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.在汇编语言中, 标号代表一个地址
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.loop指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span><span style="color: rgba(0, 0, 0, 1)"> loop 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> a. (CX) = (CX) - 0x01
b. 判断(CX)值 {=0x00 向下执行}, {!=0x00 转至loop标号处执行}
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.在汇编语言中, 以字母开头的数据要在前面补0
如:ABCDH => 0ABCDH
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.在汇编源程序中指令 {} 被编译器当做指令 {idata} 处理
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.在[]中用寄存器, 段地址默认在DS中
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.目前对于两个运算对象(8位, 16位)的类型不匹配, 结果可能越界的解决方法
用一个16位寄存器将其高8位置0, 用其低8位做中介
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.用于显示指明内存单元的段地址成为段前缀
第六章包含多个段的程序
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.合法的通过操作系统取得的空间都是安全的
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.伪指令dw(Define Word)定义字型数据(双字节)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> dw 0123H, 3456H [,...]
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.可执行文件中的描述信息主要是编译链接程序对源程序中的伪指令进行处理得到的
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.若dw定义的数据处于代码段的最开始, 则偏移地址是0x00, 段地址是cs
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.段名相当于一个标号(数值), 代表段地址
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.8086CPU不支持将数据直接送入段寄存器(温故)
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.伪指令db(Define Byte)定义字节数据(单字节)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> db 01H, 23H [,...]
db </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">...</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">字符串</span>
<span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.段数据所占空间为10H倍数, 不足空间补零
第七章更灵活的定位内存地址的方法
</span><span style="color: rgba(128, 0, 128, 1)">0</span>.转大写字母 {<span style="color: rgba(0, 0, 255, 1)">and</span> al, 0DFH}(11<span style="color: rgba(128, 0, 128, 1)">011111B</span>), 转小写字母 {<span style="color: rgba(0, 0, 255, 1)">or</span> al, 020H}(<span style="color: rgba(128, 0, 128, 1)">00100000B</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.寻址方式表现形式(ds为段地址)
a. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax,
b. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, [<span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)"> + bx]
c. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, <span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">
d. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, .<span style="color: rgba(128, 0, 128, 1)">200</span>
<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.寄存器di,si功能同BX相近, 但他们不能分成两个8位寄存器来使用
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.寻址方式表现形式
a. </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ax,
b. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax,
c. </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ax,
d. </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ax,
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.寻址方式表现形式
a. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax,
b. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, [<span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)"> + bx + si/di]
c. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, <span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">
d. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, .<span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">
e. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> ax, .<span style="color: rgba(128, 0, 128, 1)">200</span>
<span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.在需要暂存数据时, 应该使用栈(寄存器太少)
第八章数据处理的连个基本问题
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.在机器指令中必须明确或隐含说明处理的数据及其长度
</span><span style="color: rgba(128, 0, 128, 1)">1</span>.在8086CPU中,只有bx, si, di, bp寄存器可以用在<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">[...]</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">的寻址方式中
a.
b.
c.
</span><span style="color: rgba(128, 0, 128, 1)">2</span>.只要在<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">[...]</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">中使用bp, 而指令中没有明确的给出段地址, 则段地址默认在ss中
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.指令执行前, 要处理的数据所在位置
a. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> bx, [<span style="color: rgba(128, 0, 128, 1)">0</span>]=>内存, <span style="color: rgba(0, 128, 128, 1)">ds:</span><span style="color: rgba(0, 0, 0, 1)">0单元
b. </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> bx, ax =>CPU内部, ax寄存器
c. </span><span style="color: rgba(0, 0, 255, 1)">mov</span> bx, <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> =>CPU内部, 指令缓冲器(立即数)
</span><span style="color: rgba(128, 0, 128, 1)">4</span>.在没有寄存器参与的内存单元访问指令中用 <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">word/byte ptr</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> 指明访问内存单元的长度
a. </span><span style="color: rgba(0, 0, 255, 1)">add</span> word ptr <span style="color: rgba(0, 128, 128, 1)">ds:</span>[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">], 10H
b. </span><span style="color: rgba(0, 0, 255, 1)">inc</span><span style="color: rgba(0, 0, 0, 1)"> byte ptr , 02H
</span><span style="color: rgba(128, 0, 128, 1)">5</span>.表达式<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">被除数 ÷ 除数= 商 ··· 余数</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> 的汇编映射
a. AX(word) (byte) AL AH
b. DX(word)+AX(word)(word) AX DX
高16位 低16位
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">div</span><span style="color: rgba(0, 0, 0, 1)"> 除数(寄存器/内存单元)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">div</span><span style="color: rgba(0, 0, 0, 1)"> bl
</span><span style="color: rgba(0, 0, 255, 1)">div</span> word ptr <span style="color: rgba(0, 128, 128, 1)">es:</span>[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">]
</span><span style="color: rgba(0, 128, 128, 1)">技巧:</span><span style="color: rgba(0, 0, 0, 1)"> 对折看, 折叠点除数
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.伪指令dd(Define Double-Word)定义双字型数据(四字节)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> dd 01234567H, 89abcdefH [,...]
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.伪指令dup来进行数据重复定义
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span><span style="color: rgba(0, 0, 0, 1)"> db/dw/dd 重复次数 dup (重复的数据集合)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> dw <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> dup (1234H, 5678H)=>dw 1234H, 5678H, 1234H, 5678H
第九章转移指令的原理
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.操作符 offset 取得标号的偏移地址
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ax, offset sMain
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.可以修改IP, 或同时修改cs和ip的指令统称为转移指令
a. 段内转移, 只修改ip(短转移/近转移)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> ax
b. 段间转移, 同时修改cs和ip
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> far ptr 标号
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.8086CPU的转移指令分为
a. 无条件转移指令
b. 条件转移指令
c. 循环指令
d. 中断
e. 过程
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.jmp指令的位移计算是补码方式(符号位不变, 取反加一)
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.nop指令的机器码占一个字节
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.jmp指令要给出两种信息
a.转移的距离(段内短转移, 段内近转移, 段间转移)
b.转移的目的地址
</span><span style="color: rgba(128, 0, 128, 1)">6</span>.无条件转移指令 <span style="color: rgba(0, 0, 255, 1)">jmp</span> 转移指令结束后, <span style="color: rgba(0, 128, 128, 1)">cs:</span><span style="color: rgba(0, 0, 0, 1)">ip指向标号处的指令(编译器根据标号计算IP的转移的位移)
a.段内短转移(byte)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> short 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (IP) = (IP) + 8位位移(= 标号处的地址 - jmp指令后的第一个字节的地址)
b.段内近转移(word)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> near ptr 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (IP) = (IP) + 16位位移(= 标号处的地址 - jmp指令后的第一个字节的地址)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> 寄存器(16位)
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (IP) = (寄存器的值, 是转移的目的偏移地址)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> word ptr 内存单元地址处一个字
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (IP) = (内存单元地址处一个字的值, 是转移的目的偏移地址)
c.段间转移(远转移)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> far ptr 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (CS) = 标号所在段的段地址, (IP) = 标号所在段的偏移地址
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> dword ptr 内存单元地址处两个字
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (CS) = 高地址处的一个字的值, (IP) = 低地址处的一个字的值
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.所有的(有条件转移, 循环)指令都是短转移(机器码中包含转移的位移, 不是目的地址)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">jcxz</span><span style="color: rgba(0, 0, 0, 1)"> 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> if(0x00 == (CX))
</span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> short 标号
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span><span style="color: rgba(0, 0, 0, 1)"> loop 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> a. (CX) = (CX) - 0x01
b. if(0x00 != (CX))
</span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> short 标号
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.dec指令的功能和inc指令相反
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">dec</span><span style="color: rgba(0, 0, 0, 1)"> bx
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (BX) = (BX) - 0x01
第十章 CALL和RET指令
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.复习jmp指令
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.近转移指令ret(用栈中的数据修改ip)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">ret</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> <span style="color: rgba(0, 0, 255, 1)">pop</span><span style="color: rgba(0, 0, 0, 1)"> ip
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.远转移指令retf(用栈中的数据修改cs和ip)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">retf</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">pop</span><span style="color: rgba(0, 0, 0, 1)"> ip
b. </span><span style="color: rgba(0, 0, 255, 1)">pop</span><span style="color: rgba(0, 0, 0, 1)"> cs
</span><span style="color: rgba(128, 0, 128, 1)">3</span>.转移指令call(将ip/<span style="color: rgba(0, 128, 128, 1)">cs:</span><span style="color: rgba(0, 0, 0, 1)">ip入栈, 然后转移)
a.段内转移(= 标号处的地址 - call指令后的第一个字节的地址)(匹配ret)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
b. </span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> near ptr 标号
b.段间转移((CS) = 标号所在段的段地址, (IP) = 标号所在段的偏移地址)(匹配retf)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> far ptr 标号
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> cs
b. </span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
c. </span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> far ptr 标号
c.段内转移(寄存器的值, 是转移的目的偏移地址)(匹配ret)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> 寄存器(16bit)
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
b. </span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> 寄存器(16位)
d.段内转移(内存单元地址处一个字的值, 是转移的目的偏移地址)(匹配ret)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> word ptr 内存单元地址
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
b. </span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> word ptr 内存单元地址处一个字
e.段间转移((CS) = 高地址处的一个字的值, (IP) = 低地址处的一个字的值)(匹配retf)
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> dword ptr 内存单元地址
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> cs
b. </span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
c. </span><span style="color: rgba(0, 0, 255, 1)">jmp</span><span style="color: rgba(0, 0, 0, 1)"> dword ptr 内存单元地址处两个字
</span><span style="color: rgba(128, 0, 128, 1)">4</span>.表达式 <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">因子 x 因子 = 积</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> 的汇编映射
a. (byte) AL(byte) AX(word)
b. (word) AX(word) DX(word)+AX(word)
高16位 低16位
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">mul</span><span style="color: rgba(0, 0, 0, 1)"> 因子(寄存器/内存单元)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">mul</span> byte ptr <span style="color: rgba(0, 128, 128, 1)">es:</span>[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">]
</span><span style="color: rgba(0, 0, 255, 1)">mul</span> word ptr <span style="color: rgba(0, 128, 128, 1)">es:</span>[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">]
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.用div指令做除法时, 如果结果超出了寄存器所能存储的范围, CPU将引发称为除法溢出的内部错误
</span><span style="color: rgba(128, 0, 128, 1)">6</span>. X / N = <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">(H / N) * 10000H + / N
</span><span style="color: rgba(0, 128, 128, 1)">X:</span>被除数[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, FFFFFFFF]
</span><span style="color: rgba(0, 128, 128, 1)">N:</span>除数[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, FFFF]
</span><span style="color: rgba(0, 128, 128, 1)">H:</span>X高16位[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, FFFF]
</span><span style="color: rgba(0, 128, 128, 1)">L:</span>X低16位[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, FFFF]
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">():取商
rem():取余
第十一章标志寄存器
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.大多数传送指令的执行对标志寄存器没有影响
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.标志寄存器的作用
a.用来存储相关指令的某些执行结果
b.用来为CPU执行相关指令提供行为依据
c.用来控制CPU的相关工作方式
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.标志寄存器的结构
索引 -> </span><span style="color: rgba(128, 0, 128, 1)">0F</span><span style="color: rgba(128, 0, 128, 1)">0E</span><span style="color: rgba(128, 0, 128, 1)">0D</span><span style="color: rgba(128, 0, 128, 1)">0C</span><span style="color: rgba(128, 0, 128, 1)">0B</span><span style="color: rgba(128, 0, 128, 1)">0A</span><span style="color: rgba(128, 0, 128, 1)">09</span><span style="color: rgba(128, 0, 128, 1)">08</span><span style="color: rgba(128, 0, 128, 1)">07</span><span style="color: rgba(128, 0, 128, 1)">06</span><span style="color: rgba(128, 0, 128, 1)">05</span><span style="color: rgba(128, 0, 128, 1)">04</span><span style="color: rgba(128, 0, 128, 1)">03</span><span style="color: rgba(128, 0, 128, 1)">02</span><span style="color: rgba(128, 0, 128, 1)">01</span><span style="color: rgba(128, 0, 128, 1)">00</span><span style="color: rgba(0, 0, 0, 1)">
标志 -> OFDFIFTFSFZF AF PF CF
假=</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> -> NVUPDI PLNZ NA PO NC
真=</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> -> OVDNEI NGZR AC PE CY
词汇 -> NV(</span><span style="color: rgba(0, 0, 255, 1)">Not</span><span style="color: rgba(0, 0, 0, 1)"> Overflow)UP(Up) DI(Disable Interrupt)PL(Positive)
-> OV(Overflow) DN(Down)EI(Enable Interrupt) NG(Negative)
-> NZ(</span><span style="color: rgba(0, 0, 255, 1)">Not</span><span style="color: rgba(0, 0, 0, 1)"> Zero)NA(No Auxiliary Carry)PO(Parity Odd) NC(No Carry)
-> ZR(Zero) AC(Auxiliary Carry) PE(Parity Even)CY(Carry)
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.标志寄存器的行为
ZF(Zero-Flag)记录相关指令执行后其结果是否为0x00
PF(Parity-Flag)记录相关指令执行后其结果的所有Bit位中的1的个数是否为偶数
SF(Sign-Flag)记录相关指令执行后其结果是否为负值
CF(Carry-Flag)记录相关指令执行后其结果的最高有效位是否向更高位进位/借位
OF(Overflow-Flag)记录相关指令执行后其结果是否发生了溢出(值超出范围)
DF(Direction-Flag)方向标志位, 在串处理指令中, 控制每次操作后SI, DI的增减方式
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.标志寄存器的意义
SF标志是在将数据当作有符号来运算时通过其值得知结果的正负, 在将数据当作无符号来运算时虽然结果影响其值但忽略其意义(对寄存器值而言)
CF标志对无符号数运算有意义(逻辑值对寄存器值而言)
OF标志对有符号数运算有意义(逻辑值对寄存器值而言)
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.adc指令是带进位加法指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">adc</span><span style="color: rgba(0, 0, 0, 1)"> 操作对象1, 操作对象2
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (操作对象1) = (操作对象1) + (操作对象2) + (CF)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">adc</span><span style="color: rgba(0, 0, 0, 1)"> ax, bx
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (AX) = (AX) + (BX) + (CF)
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.sbb指令是带进位减法指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">sbb</span><span style="color: rgba(0, 0, 0, 1)"> 操作对象1, 操作对象2
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (操作对象1) = (操作对象1) - (操作对象2) - (CF)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">sbb</span><span style="color: rgba(0, 0, 0, 1)"> ax, bx
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (AX) = (AX) - (BX) - (CF)
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.cmp指令比较指令, 功能相当于减法, 只是不保存结果, 暂存在CPU内部的暂存器中
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">cmp</span><span style="color: rgba(0, 0, 0, 1)"> 操作对象1, 操作对象2
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> 计算 (操作对象1) - (操作对象2), 根据结果对标志寄存器进行设置
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">cmp</span><span style="color: rgba(0, 0, 0, 1)"> ax, bx
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> 计算 (AX) - (BX), 结果影响标志寄存器的相关各位值
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.cmp指令进行无符号数比较结果
if((AX) == (BX)) { ZF=</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) != (BX)) { ZF=</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX)< (BX)) { CF=</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) =< (BX)) { CF=</span><span style="color: rgba(128, 0, 128, 1)">1</span> || ZF=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) >(BX)) { CF=</span><span style="color: rgba(128, 0, 128, 1)">0</span> && ZF=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) >= (BX)) { CF=</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.cmp指令进行有符号数比较结果
if((AX) == (BX)) { ZF=</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) != (BX)) { ZF=</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) <(BX)) {(SF=</span><span style="color: rgba(128, 0, 128, 1)">1</span> && OF=<span style="color: rgba(128, 0, 128, 1)">0</span>) || (SF=<span style="color: rgba(128, 0, 128, 1)">0</span> && OF=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">)}
if((AX) <= (BX)) {}
if((AX) >(BX)) { SF=</span><span style="color: rgba(128, 0, 128, 1)">1</span> && OF=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> }
if((AX) >= (BX)) { SF=</span><span style="color: rgba(128, 0, 128, 1)">0</span> && OF=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(128, 0, 128, 1)">10</span>.所有条件转移指令的转移位移都是[-<span style="color: rgba(128, 0, 128, 1)">128</span>, <span style="color: rgba(128, 0, 128, 1)">127</span><span style="color: rgba(0, 0, 0, 1)">]
</span><span style="color: rgba(128, 0, 128, 1)">11</span><span style="color: rgba(0, 0, 0, 1)">.根据无符号数的比较结果进行转移的条件转移指令
格式 -> 指令 标号
指令 -> </span><span style="color: rgba(0, 0, 255, 1)">je</span> <span style="color: rgba(0, 0, 255, 1)">jne</span> <span style="color: rgba(0, 0, 255, 1)">jb</span> <span style="color: rgba(0, 0, 255, 1)">jnb</span> <span style="color: rgba(0, 0, 255, 1)">ja</span> <span style="color: rgba(0, 0, 255, 1)">jna</span><span style="color: rgba(0, 0, 0, 1)">
含义 -> == != < >= > <=
标志 -> ZF=</span><span style="color: rgba(128, 0, 128, 1)">1</span> ZF=<span style="color: rgba(128, 0, 128, 1)">0</span> CF=<span style="color: rgba(128, 0, 128, 1)">1</span> CF=<span style="color: rgba(128, 0, 128, 1)">0</span> CF=<span style="color: rgba(128, 0, 128, 1)">0</span> && ZF=<span style="color: rgba(128, 0, 128, 1)">0</span> CF=<span style="color: rgba(128, 0, 128, 1)">1</span> || ZF=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
词汇 -> j(Jump)
-> a(Above)na(</span><span style="color: rgba(0, 0, 255, 1)">Not</span><span style="color: rgba(0, 0, 0, 1)"> Above)
-> b(Below)nb(</span><span style="color: rgba(0, 0, 255, 1)">Not</span><span style="color: rgba(0, 0, 0, 1)"> Below)
-> e(Equal)ne(</span><span style="color: rgba(0, 0, 255, 1)">Not</span><span style="color: rgba(0, 0, 0, 1)"> Equal)
</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">.movsb串传送指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">movsb</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">mov</span> <span style="color: rgba(0, 128, 128, 1)">es:</span>, byte ptr <span style="color: rgba(0, 128, 128, 1)">ds:</span><span style="color: rgba(0, 0, 0, 1)">
b. if(0x00 == (DF))
</span><span style="color: rgba(0, 0, 255, 1)">inc</span><span style="color: rgba(0, 0, 0, 1)"> si
</span><span style="color: rgba(0, 0, 255, 1)">inc</span><span style="color: rgba(0, 0, 0, 1)"> di
c. if(0x01 == (DF))
</span><span style="color: rgba(0, 0, 255, 1)">dec</span><span style="color: rgba(0, 0, 0, 1)"> si
</span><span style="color: rgba(0, 0, 255, 1)">dec</span><span style="color: rgba(0, 0, 0, 1)"> di
</span><span style="color: rgba(128, 0, 128, 1)">13</span><span style="color: rgba(0, 0, 0, 1)">.movsw串传送指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">movsw</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">mov</span> <span style="color: rgba(0, 128, 128, 1)">es:</span>, word ptr <span style="color: rgba(0, 128, 128, 1)">ds:</span><span style="color: rgba(0, 0, 0, 1)">
b. if(0x00 == (DF))
</span><span style="color: rgba(0, 0, 255, 1)">add</span><span style="color: rgba(0, 0, 0, 1)"> si, 02H
</span><span style="color: rgba(0, 0, 255, 1)">add</span><span style="color: rgba(0, 0, 0, 1)"> di, 02H
c. if(0x01 == (DF))
</span><span style="color: rgba(0, 0, 255, 1)">sub</span><span style="color: rgba(0, 0, 0, 1)"> si, 02H
</span><span style="color: rgba(0, 0, 255, 1)">sub</span><span style="color: rgba(0, 0, 0, 1)"> di, 02H
</span><span style="color: rgba(128, 0, 128, 1)">14</span><span style="color: rgba(0, 0, 0, 1)">.rep指令根据(CX)值重复执行后面的串传送指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">rep</span> <span style="color: rgba(0, 0, 255, 1)">movsb</span>/<span style="color: rgba(0, 0, 255, 1)">movsw</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> <span style="color: rgba(0, 128, 128, 1)">s:</span><span style="color: rgba(0, 0, 255, 1)">movsb</span>/<span style="color: rgba(0, 0, 255, 1)">movsw</span><span style="color: rgba(0, 0, 0, 1)">
loop s
</span><span style="color: rgba(128, 0, 128, 1)">15</span><span style="color: rgba(0, 0, 0, 1)">.cld指令将(DF)标志位值置0
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">cld</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> (DF)=<span style="color: rgba(128, 0, 128, 1)">0</span>
<span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">.std指令将(DF)标志位值置1
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">std</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> (DF)=<span style="color: rgba(128, 0, 128, 1)">1</span>
<span style="color: rgba(128, 0, 128, 1)">17</span><span style="color: rgba(0, 0, 0, 1)">.pushf指令将标志寄存器的值压栈
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">pushf</span>
<span style="color: rgba(128, 0, 128, 1)">18</span><span style="color: rgba(0, 0, 0, 1)">.popf指令从栈中弹出数据送入标志寄存器中
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">popf</span><span style="color: rgba(0, 0, 0, 1)">
第十二章内中断
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.中断是指CPU不再接着刚执行完的指令向下执行, 而是转去处理中断信息
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.中断信息是CPU在执行完当前的指令后, 检测到从外部或内部产生的并立即进行处理的特殊信息
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.中断信息的产生
a.除法错误, 类型码 </span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
b.单步执行, 类型码 </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
c.执行into指令, 类型码 </span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">
d.执行int指令, 类型码 指令中的立即数
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.中断向量是中断处理程序的入口地址
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.中断向量表是中断处理程序的入口地址列表
</span><span style="color: rgba(128, 0, 128, 1)">5</span>.<span style="color: rgba(0, 128, 128, 1)">对于8086CPU中断向量表指定存放在内存0000:</span><span style="color: rgba(128, 0, 128, 1)">0000</span>~<span style="color: rgba(128, 0, 128, 1)">0000</span>:03FF的1024个单元中, <span style="color: rgba(128, 0, 128, 1)">0000</span>:<span style="color: rgba(128, 0, 128, 1)">0200</span>~<span style="color: rgba(128, 0, 128, 1)">0000</span><span style="color: rgba(0, 0, 0, 1)">:02FF对应的中断向量表一般是空的
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.在中断向量表中, 一个表项存放一个中断向量即一个中断处理程序的入口地址
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.一个表项占两个字, 低地址字存放偏移地址, 高地址字存放段地址
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.中断过程(由硬件自动执行)
a.取得中断类型码N
b.</span><span style="color: rgba(0, 0, 255, 1)">pushf</span><span style="color: rgba(0, 0, 0, 1)">
c.(TF)=</span><span style="color: rgba(128, 0, 128, 1)">0</span>, (IF)=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
d.</span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> cs
e.</span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
f.(IP)=(N * 04H), (CS)=(N * 04H + 02H)
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.编写中断处理程序常规步骤
a.保存用到的寄存器
b.处理中断
c.恢复用到的寄存器
e.用iret指令返回
</span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">.iret指令通常和硬件自动完成的中断过程配合使用
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">iret</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> a. <span style="color: rgba(0, 0, 255, 1)">pop</span><span style="color: rgba(0, 0, 0, 1)"> ip
b. </span><span style="color: rgba(0, 0, 255, 1)">pop</span><span style="color: rgba(0, 0, 0, 1)"> cs
c. </span><span style="color: rgba(0, 0, 255, 1)">popf</span>
<span style="color: rgba(128, 0, 128, 1)">11</span>.CPU执行完一条指令后, 如果(TF)=1则产生单步中断, 所以在进入中断处理程序前设置(TF)=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, 避免在处理中断程序时发生单步中断
</span><span style="color: rgba(128, 0, 128, 1)">12</span>.在执行完向ss寄存器传送数据指令后, 即使发生中断, CPU也不会响应, <span style="color: rgba(0, 128, 128, 1)">保证ss:</span><span style="color: rgba(0, 0, 0, 1)">sp指向正确的栈顶
第十三章int指令
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.int指令由中断类型码引发中断过程
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> n
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.CPU执行int n指令引发一个n号中断的中断过程
a.取中断类型码N
b.标志寄存器入栈
c.(TF)=</span><span style="color: rgba(128, 0, 128, 1)">0</span>, (IF)=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
d.</span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> cs
e.</span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
f.(IP)=(N * 04H), (CS)=(N * 04H + 02H)
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.中断处理程序简称中断例程
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.在系统板的ROM中存放着称为BIOS(基本输入输出系统)的程序, 主要包含
a.硬件系统的检测和初始化程序
b.外部中断和内部中断的中断例程
c.用于对硬件设备进行I/O操作的中断例程
d.其他和硬件系统相关的中断例程
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.BIOS和DOS提供的中断例程安装到内存的过程
a.</span><span style="color: rgba(0, 128, 128, 1)">CPU加电初始化cs:</span>ip=<span style="color: rgba(0, 128, 128, 1)">FFFF:</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, 此处有一条跳转指令, CPU执行该指令后转去执行BIOS中的硬件系统检测和初始化程序
b.初始化程序将BIOS提供的中断例程的入口地址登记在中断向量表中, 中断例程是固化在ROM中的
c.硬件系统检测和初始化完成后, 调用int 19H进行操作系统的引导, 将计算机交给操作系统控制
d.DOS启动后, 除完成其他工作外, 还将它提供的中断例程装入内存, 建立相应的中断向量
</span><span style="color: rgba(128, 0, 128, 1)">5</span>.<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 21H是DOS提供的中断例程, 返回功能mov ax 4c00H是4cH号子程序00H返回值
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.设置光标位置功能例子
</span><span style="color: rgba(0, 0, 255, 1)">mov</span> ah, 02H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">int 10H功能2号子程序</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> bh, 00H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">屏幕页号</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> dh, 05H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">屏幕行号</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> dl, 0CH <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">屏幕列号</span>
<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 10H
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.在光标位置显示字符功能例子
</span><span style="color: rgba(0, 0, 255, 1)">mov</span> ah, 09H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">int 10H功能9号子程序</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> al, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">显示的字符</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> bl, 07H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">显示的字符的属性</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> bh, 00H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">屏幕页号</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> cx, 03H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">重复显示字符的数量</span>
<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 10H
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.在光标位置显示字符串功能例子
</span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ds, 00H
</span><span style="color: rgba(0, 0, 255, 1)">mov</span> dx, 00H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">ds:dx指向以'$'结尾要显示的字符串</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> ah, 09H <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)">int 21H功能9号子程序</span>
<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 21H
第十四章端口
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.CPU在操控各种储存器时把它们总体看作一个由若干存储单元组成的逻辑存储器(内存地址空间)
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.和CPU通过总线相连的芯片除了各种存储器还有
a.各种接口卡上的接口芯片, 它们控制接口卡工作
b.主板上的接口芯片, CPU通过它们对部分外设进行访问
c.其他芯片, 用来存储相关的系统信息, 或进行相关的输入输出处理
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.这些芯片都有一组可以由CPU读写的寄存器, 在物理上可能处于不同的芯片中, 但以下相同
a.都和CPU的总线相连, 通过它们所在的芯片连接
b.CPU对它们的读写都通过控制线向它们所在的芯片发出端口读写命令
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.从CPU的角度, 将这些寄存器都当作端口, 对它们进行统一编址, 建立统一的端口地址空间, 每个端口在地址空间上都有一个地址
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.CPU可以直接读写数据的地方
a.CPU内部的寄存器
b.内存单元
c.端口
</span><span style="color: rgba(128, 0, 128, 1)">5</span>.CPU通过端口地址来定位端口, 通过地址总线来传送, 端口地址范围0~<span style="color: rgba(128, 0, 128, 1)">65535</span>
<span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.in指令从端口读取数据
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> al/ax, 端口
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> al, 20H
</span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.out指令向端口写入数据
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> 端口, al/ax
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> dx, al/ax
</span><span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.在in和out指令中, 只能用al或ax来存放读取或写入端口的数据, 访问8位端口用al, 访问16位端口用ax
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.对256~65535端口进行读写时用dx存放端口号
</span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">.CMOS RAM芯片有两个不同的端口, 70H为地址端口, 71H为数据端口
</span><span style="color: rgba(128, 0, 128, 1)">11</span><span style="color: rgba(0, 0, 0, 1)">.shl逻辑左移指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">shl</span><span style="color: rgba(0, 0, 0, 1)"> 寄存器/内存单元, cl
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> a. 将寄存器或内存单元中的数据向左位移
b. 将最后移出的一Bit位写入cf中
c. 最低位用0补充
d. 相当于执行X = X * 02H
</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">.shr逻辑右移指令
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">shr</span><span style="color: rgba(0, 0, 0, 1)"> 寄存器/内存单元, cl
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> a. 将寄存器或内存单元中的数据向右位移
b. 将最后移出的一Bit位写入cf中
c. 最高位用0补充
d. 相当于执行X = X / 02H
</span><span style="color: rgba(128, 0, 128, 1)">13</span><span style="color: rgba(0, 0, 0, 1)">.逻辑位移指令的移动位数大于1时, 必须将移动位数放于cl中
</span><span style="color: rgba(128, 0, 128, 1)">14</span><span style="color: rgba(0, 0, 0, 1)">.BCD码是用4位二进制数表示一位十进制数的编码方法
第十五章外中断
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.CPU除了有运算能力外, 还有I/O(Input/Output)能力
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.外设的输入不直接送入内存和CPU, 而是送入相关的接口芯片的端口中
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.CPU向外设的输出也不直接送入外设, 而是先送入端口中, 再由相关的芯片送到外设
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.外中断源分为可屏蔽中断和不可屏蔽中断
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.可屏蔽中断是CPU可以不响应的外中断, 当CPU检测到可屏蔽中断信息时, 如果(IF)=1则CPU执行完当前指令后响应中断引发中断过程, 如果(IF)=0则不响应可屏蔽中断
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.可屏蔽中断引发的中断过程和内中断的中断过程相同, 只是中断类型码是通过数据总线送入CPU的, 而内中断的中断类型码是在CPU内部产生的
</span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">.cli指令将(IF)标志位值置0
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">cli</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> (IF)=<span style="color: rgba(128, 0, 128, 1)">0</span>
<span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">.sti指令将(IF)标志位值置1
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">sti</span>
<span style="color: rgba(0, 128, 128, 1)">功能:</span> (IF)=<span style="color: rgba(128, 0, 128, 1)">1</span>
<span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">.不可屏蔽中断是CPU必须响应的外中断, 当CPU检测到不可屏蔽中断信息时, 则在执行完当前指令后立即响应引发中断过程
</span><span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.对于8086PC不可屏蔽中断的中断类型码固定为2, 则不可屏蔽中断的中断过程是
a.标志寄存器入栈
b.(TF)=</span><span style="color: rgba(128, 0, 128, 1)">0</span>, (IF)=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
c.</span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> cs
d.</span><span style="color: rgba(0, 0, 255, 1)">push</span><span style="color: rgba(0, 0, 0, 1)"> ip
e.(IP)=(</span><span style="color: rgba(128, 0, 128, 1)">2</span> * 04H), (CS)=(<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> * 04H + 02H)
</span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">.键盘上的芯片对每个按键的开关状态产生一个扫描码送入主板上相关的接口芯片的60H端口地址的寄存器中
</span><span style="color: rgba(128, 0, 128, 1)">11</span><span style="color: rgba(0, 0, 0, 1)">.按下一个键产生的扫描码为通码, 松开一个键产生的扫描码为断码, 扫描码长度为一个字节, 断码 = 通码 + 80H
</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">.键盘的输入到达60H端口时, 相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息
</span><span style="color: rgba(128, 0, 128, 1)">13</span><span style="color: rgba(0, 0, 0, 1)">.BIOS提供了int9中断例程, 用来进行基本的键盘输入处理
a.读取60H端口中的扫描码
b.如果是字符键的扫描码, 将该扫描码和对应的ASCII码送入内存中的BIOS键盘缓冲区
c.如果是控制键和切换键的扫描码, 则将其转变为状态字节(用二进制位记录控制键和切换键状态的字节)写入内存中存储状态字节的单元
d.对键盘系统进行相关的控制
</span><span style="color: rgba(128, 0, 128, 1)">14</span><span style="color: rgba(0, 0, 0, 1)">.BIOS键盘缓冲区是系统启动后, BIOS用于存放int9中断例程所接收的键盘输入的内存区, 一个键盘输入用一个字单元存放, 高位字节存放扫描码, 低位字节存放字符码
</span><span style="color: rgba(128, 0, 128, 1)">15</span>.<span style="color: rgba(128, 0, 128, 1)">0040</span><span style="color: rgba(0, 0, 0, 1)">:17单元存储键盘状态字节, 各位记录的信息
a. </span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">:右Shift状态, 置1表示按下右Shift键
b. </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">:左Shift状态, 置1表示按下左Shift键
c. </span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">:Ctrl状态, 置1表示按下Ctrl键
h. </span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">:Alt状态, 置1表示按下Alt键
d. </span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">:ScrollLock状态, 置1表示Scroll灯亮
e. </span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">:NumLock状态, 置1表示小键盘输入的是数字
f. </span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">:CapsLock状态, 置1表示输入大写字母
g. </span><span style="color: rgba(128, 0, 128, 1)">7</span><span style="color: rgba(0, 0, 0, 1)">:Insert状态, 置1表示处于删除态
</span><span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">.键盘输入的处理过程
a.键盘产生扫描码
b.扫描码送入60H端口
c.引发9号中断
d.CPU执行int9中断例程处理键盘输入
</span><span style="color: rgba(128, 0, 128, 1)">17</span><span style="color: rgba(0, 0, 0, 1)">.读出键盘的输入
</span><span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> al, 60H
第十六章直接定址表
</span><span style="color: rgba(128, 0, 128, 1)">0</span>.在标号后面有<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">号时, 标号描述内存地址, 此标号只能在代码段中使用
</span><span style="color: rgba(128, 0, 128, 1)">1</span>.在标号后面没有<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">号时, 标号同时描述内存地址和单元长度(字节, 字, 双字), 此标号代表一个段中的内存单元, 称为数据标号
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.如果在代码段中直接用数据标号访问数据, 则需要用伪指令assume将标号所在的段和一个段寄存器联系起来
</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">.可以将数据标号当作数据来定义, 此时编译器将数据标号所表示的地址值当作数据的值
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> data segment
a db ...
b dw ...
c dw a, b
data ends
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> data segment
a db ...
b dw ...
c dw offset a, offset b
data ends
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.seg操作符为取得某一标号的段地址
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span><span style="color: rgba(0, 0, 0, 1)"> data segment
a db ...
b dw ...
c dd a, b
data ends
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> data segment
a db ...
b dw ...
c dw offset a, seg a, offset b, seg b
data ends
</span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.直接定址表是通过数据直接计算出要找的元素的位置的表
第十七章使用BIOS进修键盘输入和磁盘读写
</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">.键盘输入将引发9号中断, CPU在9号中断发生后执行int 9H中断例程, 从60H端口读出扫描码, 将其转化为相应的ASCII码或状态信息, 存储在键盘缓冲区或状态字中
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.键盘缓冲区有16个字单元是环形队列结构管理的内存, 高字节存储扫描码, 低字节存储ASCII码
</span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.BIOS提供了int 16H的0号功能从键盘缓冲区读取一个键盘输入, 并将其从缓冲区中删除
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> a.检测键盘缓冲区中是否有数据
b.没有则继续第一步
c.读取缓冲区第一个字单元的键盘输入
d.将读取的扫描码送入ah, ASCII码送入al
e.将已读取的键盘输入从缓冲区中删除
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ah, 00H
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> 16H
</span><span style="color: rgba(0, 128, 128, 1)">结果:</span><span style="color: rgba(0, 0, 0, 1)"> (AH)=扫描码, (AL)=ASCII码
</span><span style="color: rgba(128, 0, 128, 1)">3</span>.<span style="color: rgba(128, 0, 128, 1)">3</span>.5<span style="color: rgba(0, 128, 128, 1)">英寸的软盘:</span><span style="color: rgba(0, 0, 0, 1)">
a. 分为上下两面(磁头), 面号从0开始
b. 每面有80个磁道, 磁道号从0开始
c. 每个磁道有18个扇区, 扇区号从1开始
d. 每个扇区有512个字节
</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">.BIOS提供访问磁盘的int 13H中断例程
</span><span style="color: rgba(0, 128, 128, 1)">参数:</span><span style="color: rgba(0, 0, 0, 1)"> ah=功能号02H读扇区, 03H写扇区
al=读写的扇区数
cl=扇区号(01H~12H)
ch=磁道号(00H~4FH)
dh=面号(00H~01H)(磁头)
dl=驱动器号(00</span><span style="color: rgba(0, 128, 128, 1)">H:</span>软驱A, 01<span style="color: rgba(0, 128, 128, 1)">H:</span>软驱B, 80<span style="color: rgba(0, 128, 128, 1)">H:</span>硬盘C, 81<span style="color: rgba(0, 128, 128, 1)">H:</span><span style="color: rgba(0, 0, 0, 1)">硬盘D)
</span><span style="color: rgba(0, 128, 128, 1)">es:</span><span style="color: rgba(0, 0, 0, 1)">bx=指向读取或写入的数据内存区
</span><span style="color: rgba(0, 128, 128, 1)">结果:</span><span style="color: rgba(0, 0, 0, 1)"> 返回成功(ah)=00H, (al)=读入的扇区数
返回失败(ah)=错误码
综合研究
</span><span style="color: rgba(128, 0, 128, 1)">0</span>.在TC <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">.0下C语言中main函数地址为0x01FA
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.C语言将函数实现为汇编语言中的子程序
</span><span style="color: rgba(128, 0, 128, 1)">2</span>.C <span style="color: rgba(0, 128, 128, 1)">语言:</span> *(char*)0x2000 = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 128, 0, 1)">;
</span> <span style="color: rgba(0, 128, 128, 1)">伪汇编:</span> <span style="color: rgba(0, 0, 255, 1)">mov</span> byte ptr <span style="color: rgba(0, 128, 128, 1)">ds:</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(128, 0, 128, 1)">3</span>.C <span style="color: rgba(0, 128, 128, 1)">语言:</span> *(<span style="color: rgba(0, 0, 255, 1)">int</span>*)0x2000 = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 128, 0, 1)">;
</span> <span style="color: rgba(0, 128, 128, 1)">伪汇编:</span> <span style="color: rgba(0, 0, 255, 1)">mov</span> word ptr <span style="color: rgba(0, 128, 128, 1)">ds:</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(128, 0, 128, 1)">4</span>.C <span style="color: rgba(0, 128, 128, 1)">语言:</span> *(char far*)0x20001000 = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 128, 0, 1)">;
</span> <span style="color: rgba(0, 128, 128, 1)">伪汇编:</span> <span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> es, 2000H
</span><span style="color: rgba(0, 0, 255, 1)">mov</span> <span style="color: rgba(0, 128, 128, 1)">es:</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">.xor指令异或运算, 同0异1
</span><span style="color: rgba(0, 128, 128, 1)">格式:</span> <span style="color: rgba(0, 0, 255, 1)">xor</span><span style="color: rgba(0, 0, 0, 1)"> 操作对象1, 操作对象2
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">xor</span> (AX=<span style="color: rgba(128, 0, 128, 1)">1</span>), (BX=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (AX) = (AX)
</span><span style="color: rgba(0, 128, 128, 1)">例子:</span> <span style="color: rgba(0, 0, 255, 1)">xor</span> (AX=<span style="color: rgba(128, 0, 128, 1)">0</span>), (BX=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">功能:</span><span style="color: rgba(0, 0, 0, 1)"> (AX) = (BX)
附注
</span><span style="color: rgba(128, 0, 128, 1)">0</span>.<span style="color: rgba(0, 0, 255, 1)">ret</span><span style="color: rgba(0, 0, 0, 1)"> n指令将栈顶指针修改为调用前的值, n为调用子程序前压入栈中的参数数量*02H
</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">.详情看书吧
欢迎关注 iF8s 微信公共号
</span></pre>
</div>
<p>课程设计2部分效果图</p>
<p><img src="https://img2020.cnblogs.com/blog/511414/202112/511414-20211213231034421-1130306171.png" alt="" loading="lazy"></p>
<p> <img src="https://img2020.cnblogs.com/blog/511414/202112/511414-20211213231047204-384235302.png" alt="" loading="lazy"></p>
<p> <img src="https://img2020.cnblogs.com/blog/511414/202112/511414-20211213231113963-1503241493.png" alt="" loading="lazy"></p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<br/>
<img src="https://files.cnblogs.com/files/wjshan0808/0.bmp" /><br><br>
来源:https://www.cnblogs.com/wjshan0808/p/15685803.html
頁:
[1]