汇编学习杂记(9~13章)

本文介绍了8086汇编语言中的补码表示法,8位和16位有符号数的范围,并详细讲解了显示缓冲区的布局。此外,还探讨了汇编语言中的转移指令,包括短转移、近转移和远转移,以及条件转移指令。文章进一步阐述了循环指令和子程序设计的标准框架,并详细解析了8086CPU的标志寄存器,包括零标志位、奇偶标志位、符号标志位、进位标志位和溢出标志位,以及如何使用这些标志进行条件判断和比较。最后,介绍了中断处理程序的执行流程和中断向量表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

补码(8位有符号数范围 -128 ~ 127 , 16位有符号数范围 -32768 ~ 32767)
最高位为1,表示负数;
正数补码取反加1后,为其对应的负数补码;负数补码取反加1后,为其绝对值.
例:1的补码:00000001b,取反加1后为:11111111b,表示-1;
10000000b,取反加1后为:10000000b,大小为128,所以这个码就表示-128

 

显示缓冲区(80 * 25 每行80个字符一共25行 一共分为8页 B8000H ~ BFFFFH)
第一页:B800:0000 ~ B800:0F9F (0 ~ 3999)
000 ~ 09F 对应第0行(80个字符占位160个字符) (0 ~ 159)
0A0 ~ 13F 对应第1行(160 ~ 319)
140 ~ 1DF 对应第2行
F00 ~ F9F 对应第24行
一个字符占两个字节,低位存放ASCII码.高位存放属性
00 ~ 01 对应第0列
02 ~ 03 对应第1列
9E ~ 9F 对应第79列
属性字节的格式: 7   6   5   4             3     2   1   0
R:红色             BL  R   G   B             I      R   G   B
G:绿色            闪烁 ~~~~~~背景 高亮 ~~~~~~前景
B:蓝色

 

offset 伪指令,功能是取得标号的偏移地址,如: start:mov ax,offset start 相当于mov ax,0
计算代码长度 mov ax,offset 1 - offset 0
           0:需要确定长度的代码段
           1:可以是代码段也可以写个空白nop

 

转移指令
只修改IP时,称为 段内转移,比如: jmp ax (用AX的值为IP赋值)
同时修改CS和IP时,称为 段间转移,比如:jmp 1000:0
根据范围又可分为:短转移IP修改范围(-128 ~ 127) 近转移IP修改范围(-32768 ~ 32767)

 

jmp short 标号 (转到标号处执行指令) short 指明是段内短转移(功能表示为:(IP)=(IP)+8位位移)
8位位移="标号"处地址 - JMP指令后第一个字节的地址
short指明此处的为8位位移(位移范围-128 ~ 127,用补码表示)

 

jmp near ptr 标号 (段内近转移)(功能表示为:(IP)=(IP)+16位位移)

jmp far ptr 标号 (段间转移 也叫 远转移)
(功能表现为:(CS)=标号所在段的段地址;(IP)=标号所在段中的偏移地址)
例:0BBD:0006 EA0B01BD0B  JMP 0BBD:010B

jmp word ptr 内存单元地址(段内转移)
jmp dword ptr 内存单元地址(段间转移)( (CS)=(内存单元地址+2) (IP)=(内存单元地址) )

 

有条件转移指令(所有的有条件转移指令都是短转移"-128 ~ 127")
jcxz 标号 (如果(cx)=0,转移到标号处执行,否则程序向下执行)
相当于 if((cx)==0)jmp short 标号;

 

循环指令(所有的循环指令都是短转移)
loop 标号 ((cx)=(cx)-1,如果(cx)不等于0,转移到标号处执行)
操作流程:1. (cx)=(cx)-1
              2. 如果(cx)不等于0,(IP)=(IP)+8位位移

 

ret 指令用栈中的数据修改IP的内容,实现近转移(-32768 ~ 32767),相当于 pop ip
retf 指令用栈中的数据修改CS和IP的内容,实现远转移(段间转移), 相当于 pop ip  pop cs
ret n 指令格式,相当于 pop IP
                                add sp,n

 

注:在执行CALL指令时,IP的值先变成CALL指令后的第一个字节的偏移地址,然后才被压入栈.
call 标号 (将当前的IP压栈,转到标号处执行)只能是近转移(-32768 ~ 32767)16位位移
相当于 push ip
          jmp near prt 标号
call far ptr 标号 实现段间转移 相当于 push cs 
                                                      push ip 
                                                      jmp far ptr 标号
call 16位寄存器 相当于 push IP
                                  jmp 16位寄存器

call word ptr 内存单元地址 相当于 push ip
                                                  jmp word ptr 内存单元地址

call dword ptr 内存单元地址 相当于 push cs
                                                    push ip
                                                    jmp dword ptr 内存单元地址

 

call 指令将IP压栈. ret 指令且是出栈转移.从而可用CALL调用子程序,再在子程序中用ret返回。

子程序设计标准框架:
子程序对调用程序保护: 子程序中使用的寄存器入栈
               子程序开始: 子程序内容
                                子程序中使用的寄存器出栈
                               返回(ret,retf)

 

8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW)


约定:flag 表示标志寄存器
flag的1.3.5.12.13.14.15位在8086CPU中没有使用,不具任何含义

 

第6位ZF 零标志位.它记录相关指令执行后,其结果是否为0,如果为0,那么ZF=1,否则ZF=0

 

第2位PF 奇偶标志位.它记录相关指令执行后,其结果的所有二进制位中1的个数是否为偶数.如果1的个数为偶数,那么PF=1,如果为奇数,那么PF=0
如: mov al,1    注:0 也是偶数00000000B,如果是这样,PF也为1
    add al,10   执行后,结果为00001011B,其中有3(奇数)个1,则PF=0

 

第7位SF 符号标志位.它记录相关指令执行后,其结果是否为负.如果结果为负SF=1,非负SF=0

 

第0位CF 进位标志位.在进行无符号数运算时,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值.    

CF是对无符号数运算有意义的标志位
例如: mov al,98H
        add al,al   ;执行后:(al)=30H,CF=1, CF记录了从最高有效位向更高位的进位值
再如减法时: mov al,97H
                 sub al,98H  ;执行后:(al)=FFH,CF=1,相当于计算197H减去98H

 

第11位OF 溢出标志位.在进行有符号数运算时,它记录了运算结果是否发生了溢出,如果溢出OF=1,否则OF=0.              

OF是对有符号数运算有意义的标志位
例如: mov al,98  ;执行后(al)=0C5H,CF=0,OF=1,因为结果197超出了8位有符号数的范围-128 ~ 127
        add al,99  ;C5H是有符号数-59的补码,按位取反后加1,绝对值00111011B,59

 

adc 带进位加法指令 格式: adc 操作对象1,操作对象2  
                             功能: 操作对象1 = 操作对象1 + 操作对象2 + CF
用法: add al,bl
        adc ah,bh   ;相当于 add ax,bx ,低位与低位相加,高位与高位相加再加上低位的进位值

 

sbb 带借位减法指令 格式: sbb 操作对象1,操作对象2
                             功能: 操作对象1 = 操作对象1 - 操作对象2 - CF

 

cmp 比较指令 相当于减法指令,但不保存结果,执行后对标志寄存器产生影响
    格式: cmp 操作对象1,操作对象2
    功能: 计算 操作对象1 - 操作对象2 但不保存结果,仅根据结果对标志寄存器进行设置
进行无符号数比较 例: cmp ax,bx
                     ZF=1 (ax)=(bx)
                     ZF=0 (ax)≠(bx)
                     CF=1 (ax)<(bx)
                     CF=0 (ax)≥(bx)
                     CF=0 并且 ZF=0 (ax)>(bx)
                     CF=1 或 ZF=1   (ax)≤(bx)
进行有符号数比较 例: cmp ah,bh
                     ZF=1 (ah)=(bh)
                     ZF=0 (ah)≠(bh)
                     SF=1 OF=0 (ah)<(bh)
                     SF=1 OF=1 (ah)>(bh) ;如果因溢出导致了实际结果为负,那么逻辑结果为正
                     SF=0 OF=1 (ah)<(bh) ;如果因溢出导致了实际结果为正,那么逻辑结果为负
                     SF=0 OF=0 (ah)≥(bh)

 

如果SF、OF的值不相同,则说明源操作数大;
如果SF、OF的值相同,则说明源操作数小;
如果OF=1(可不考虑SF的值),则说明两种结果不相等。

整合记忆:  相异则源大;  相同则源小;  溢出则结果异。


(所有的有条件转移指令都是短转移"-128 ~ 127")
根据无符号数的比较结果进行转移的条件转移指令:
je        等于则转移  =   ZF=1                  ;jump equal
jne   不等于则转移  ≠   ZF=0                  ;jump not equal
jb        低于则转移  <   CF=1                  ;jump below
jnb   不低于则转移  ≥   CF=0                  ;jump not below
ja        高于则转移  >   CF=0 且 ZF=0    ;jump above
jna   不高于则转移  ≤   CF=1 或 ZF=1    ;jump not above

 

闭区间[32,128] 包含32.128   开区间(32,128) 不包含32.128

 

第10位DF 方向标志位 在串处理指令中,控制每次操作后si,di的增减.
DF=0 每次操作后si,di 递增;
DF=1 每次操作后si,di 递减;

movsb 串传送指令 功能: ((es)*16+(di)) = ((ds)*16+(si))
                                   如果DF=0 则: (si) = (si)+1   (di) = (di)+1
                                   如果DF=1 则: (si) = (si)-1   (di) = (di)-1
相当于 mov es:[di],byte ptr ds:[si]  ;8086并不支持这样的指令,这里只是个描述
如果DF=0; inc si   inc di
如果DF=1; dec si   dec di

 

movsw 与movsb功能相似,只是操作数为word型数据,并且si和di的增减都是2
一般,movsb和movsw都和rep指令配合使用:rep movsb 或 rep movsw
相当于 s:movsb
             loop s

rep的作用是根据CX的值,重复执行后面的串传送指令.

cld 指令: 将标志寄存器的DF位置0
std 指令: 将标志寄存器的DF位置1

 

AF 辅助进位标志 是4位运算时的进位或借位的标志位
例如: 两个8位寄存器相加,  AL=1000 0001, BL=1000 0011
        结果CF=1, AF=0      因为AL和BL的低四位相加没有进位

 

pushf和popf 指令 是压栈和出栈 标志寄存器的值
例: mov ax,0
     push ax
     popf     ;实现将标志寄存器置0

 

Debug 中标志位的表示
标志            值为1时          值为0时
OF                 OV                NV
SF                 NG                PL
ZF                 ZR                NZ
PF                 PE                PO
CF                 CY                NC
DF                 DN               UP

 

中断信息 中断的意思:CPU不再接着(刚执行完的指令)向下执行,而是转去处理这个特殊信息.

8086CPU用称为中断类型码的数据来标识中断信息的来源,中断类型码为一个字节型数据,可表示256种中断信息来源.

产生中断信息的事件,即中断信息的来源,简称为中断源.

 

8086Cpu内中断,当CPU内部有下面的情况发生时,将产生相应的中断信息:
1.除法错误,比如:执行div指令产生的除法溢出;   中断类型码:0
2.单步执行;                                                                 1
3.执行int0指令;                                                           4
4.执行int指令;该指令的格式为int n,指令中n为字节型立即数,是提供给CPU的中断类型码

 

中断向量  是中断处理程序的入口地址,对于8086CPU,一个中断向量包括段地址和偏移地址,所以占位两个字.

高地址字存放段地址,低地址字存放偏移地址

 

中断类型码 是中断向量在内存表中的索引,中断类型码0,指明中断处理程序入口地址在0000:0000到0000:0003存放,依次类推.

中断类型码 * 4 = 中断处理程序偏移地址
中断类型码 * 4 + 2 = 中断处理程序段地址

 

中断向量表 8086PC机,其存放地址必须是内存0000:0000到0000:03E8的1000个单元中.

 

中断过程 CPU用中断类型码找到中断向量,并用它设置CS和IP的过程.就叫中断过程.(硬件自动执行)
1.(从中断信息中)取得中断类型码;
2.标志寄存器的值入栈;(因为在中断过程中要改变标志寄存器的值)
3.设置标志寄存器的第8位TF和第9位IF的值为0;    ;TF置0,为了避免陷入重复的单步中断
                                                                     ;IF置0,为了在进入中断处理程序后,禁止其他的可屏蔽中断
4.CS的内容入栈;
5.IP的内容入栈;
6.从内存地址为 中断类型码*4 和 中断类型码*4+2 的两个字单元中读取中断处理程序的入口地址设置  IP和CS

 

中断处理程序 常规步骤:
1.保存用到的寄存器
2.处理中断
3.恢复用到的寄存器
4.用iret指令返回

 

iret指令用汇编语法描述:
pop ip
pop cs
popf

 

第8位TF 陷阱标志 CPU在执行完一条指令后,如果检测到TF=1,则产生单步中断,引发中断过程.中断类型码为1

 

响应中断的特殊情况 在执行完SS寄存器传送数据的指令后,CPU不会响应中断,而是紧接着执行下一条指令.因为SS:SP联合指向栈顶,而对他们的设置应该连续完成,否者中断过程的入栈指令将变得不可测.

 

int 指令格式: int n 其中n为中断类型码,功能就是引发中断过程,与iret指令配合使用可实现call指令和ret指令相配合的相似效果.

int n 调用中断例程实现循环功能
       mov bx,offset 需循环的语句 标号0 - offset 循环语句结束的下一代码处 标号1
       ;设置从 标号1 到 标号0 的转移位移(必定是个负数用补码表示)
       mov cx,循环次数
标号0: 循环的代码
       int n         ;调用中断例程
标号1: nop           ;循环语句结束

 

例程开始:     保存用到的寄存器
              mov bp,sp
              dec cx
              jcxz 例程结束标号
              add [bp+保存的寄存器数量*2],bx  
              ;bp默认段地址在SS中,当前偏移地址(标号1)+bx的负数,等于标号0的偏移地址
例程结束标号: 恢复用到的寄存器
              用iret指令返回

 

BIOS和DOS的中断例程安装过程
1.CPU加电,初始化(CS)=0FFFFH,(IP)=0,执行该处的一条跳转指令,跳转到BIOS中的硬件系统检测和初始化程序.
2.初始化程序将BIOS提供的中断例程入口地址登记在中断向量表中,(BIOS的中断例程固化在ROM中,只可读,不可写)
3.硬件系统检测和初始化完成后,调用int 19h进行操作系统引导
4.DOS启动后,除完成其他工作外,还将它所提供的中断例程装入内存,并建立中断向量

 

BIOS和DOS提供的中断例程,都用ah来传递内部子程序的编号

 

调用int 19h进行操作系统的引导:
1.根据CMOS中的系统配置选择启动操作系统的硬件设备(软盘、硬盘、光盘、U盘等)
假设从软盘启动: 控制0号软驱,读取软盘0道0面1扇区的内容到0000:7c00
2.将CS:IP指向0000:7c00.从此便交由操作系统控制计算机

 

如果0号软驱中没有软盘,或发生软盘I/O错误,
则:根据CMOS中的系统配置选择启动操作系统的备用硬件设备,如果所有的引导都错误.那么
1.读取硬盘C的0道0面1扇区的内容到0000:7c00
2.将CS:IP指向0000:7c00.从此便交由操作系统控制计算机

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值