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