《汇编语言》——王爽第三版笔记(13-15章)

书籍电子版 提取码: b62a

第13章:int指令

CPU的中断可以来自内部和外部。

int就是一种重要的内中断

int指令

int n
  1. 取中断类型码n
  2. 标志寄存器入栈,TF、IF设置为0
  3. CS、IP入栈
  4. IP = 1*n,CS = 1*n+2

编写供应用程序调用的中断例程

1. 求一个数的平方乘2
assume cs:code

code segment
    start:  mov ax, 0
            mov es, ax
            mov di, 200h

            mov ax, cs
            mov ds, ax
            mov si, offset sqr

            mov cx, offset sqrend-offset sqr
            cld
            rep movsb

            mov ax, 0
            mov es, ax
            mov word ptr es:[7ch*4], 200h
            mov word ptr es:[7ch*4+2], 0 

            mov ax, 3456
            int 7ch
            add ax, ax
            adc dx, dx

            mov ax, 4c00h
            int 21h

      sqr:  mul ax
            iret

   sqrend:  nop


code ends

end start

将求平方的程序写在0:200内存处,再将程序的入口地址放在7ch表项中,使其成为中断7ch的中断例程。

2.将内存地址上的字母小写改大写
assume cs:code, ds:data

data segment

    db 'conversation',0

data ends

code segment

    start:  
            mov ax, 0
            mov es, ax
            mov di, 200h

            mov ax, cs
            mov ds, ax
            mov si, offset interrupt

            mov cx, offset interruptend - offset interrupt
            cld
            rep movsb

            mov ax, 0
            mov es, ax
            mov word ptr es:[7ch*4], 200h
            mov word ptr es:[7ch*4+2], 0

            mov ax, data
            mov ds, ax
            mov si, 0
            int 7ch

            mov ax, 4c00h
            int 21h

interrupt: 
            push cx
            push si
        s:  
            mov cl, [si]
            mov ch, 0
            jcxz ok
            and byte ptr [si], 11011111b
            inc si
            jmp short s

       ok:
            pop si
            pop cx

            iret

interruptend: 
            nop

code ends

end start 

对int、iret和栈的深入理解

用7ch完成loop指令的功能
assume cs:code

code segment

    start:
            mov ax, 0
            mov es, ax
            mov di, 200h

            mov ax, cs
            mov ds, ax
            mov si, offset lp

            mov cx, offset lpend - offset lp

            cld
            rep movsb

            mov ax, 0
            mov es, ax
            mov word ptr es:[7ch*4], 200h
            mov word ptr es:[7ch*4 + 2], 0

            mov ax, 1800h
            mov es, ax
            mov di, 0
            mov bx, offset s - offset se
            mov cx, 80
        s:  
            mov byte ptr es:[di], '!'
            inc di
            int 7ch
            
        se: nop
        mov ax, 4c00h
        int 21h

       lp: 
            mov bp, sp
            dec cx
            jcxz lpret
            add ss:[bp], bx 

    lpret:
            iret

    lpend:
            nop
            
code ends

end start

可以推测:可以转移的最大位移应该bx的最大值:FFFFH

用7ch完成jmp near ptr s指令
assume cs:code

code segment

    start:
            mov ax, 0
            mov es, ax
            mov di, 200h

            mov ax, cs
            mov ds, ax
            mov si, offset jps

            mov cx, offset jpend - offset jps

            cld
            rep movsb

            mov ax, 0
            mov es, ax
            mov word ptr es:[7ch*4], 200h
            mov word ptr es:[7ch*4+2], 0

            mov bx, offset e - offset s
            int 7ch

        s:  nop

            mov ax, 3
            add ax, ax
            add ax, ax
            add ax, ax
            add ax, ax
            add ax, ax
            add ax, ax

        e:  nop
            mov ax, 4c00h
            int 21h

       jps:  
            push bp

            mov bp, sp
            add [bp+2], bx

    jlret:
            pop bp
            iret

    jpend:  nop


code ends
end start

BIOS和DOS所提供的中断例程

在系统板的ROM中存放着一套程序:BIOS

  1. 硬件系统的检测和初始化程序
  2. 外部中断和内部中断例程
  3. 用于对硬件设备进行I/O操作的中断例程
  4. 其他和硬件系统相关的中断例程

操作系统DOS也提供了中断例程。DOS就是操作系统向程序员提供的编程资源。

BIOS和DOS的安装过程

在这里插入图片描述

BIOS中断例程应用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

DOS中断例程应用

int 21h中断例程是DOS提供的中断例程,其中包含了DOS提供给程序员在编程时调用的子程序。

mov ah, 4ch
mov al, 0 ;返回值 
int 21h

ah = 4ch表示调用第21h号中断例程的4ch号子程序,功能为程序返回,可以提供返回值作为参数。这里的返回值就是0。

assume cs:code, ds:data

data segment

    db 'Welcome to masm!', '$'

data ends

code segment

    start:
            mov ah, 2 ;置光标
            mov bh, 0
            mov dh, 5
            mov dl, 12
            int 10h
            
            mov ax, data
            mov ds, ax
            mov dx, 0
            mov ah, 9 ;在光标处显示字符
            int 21h

            mov ax, 4c00h
            int 21h

code ends
end start

实验13编写、应用中断例程

第14章:端口

各种存储器都和CPU的三大总线相连,CPU在操控它们的时候,都把它们当作内存来看待。把它们总地看做一个由若干存储单元组成的逻辑存储器,这个逻辑存储器我们称其为内存地址空间。

和CPU相连的芯片除各种存储器外,还有以下三种:

  1. 各种接口卡上的接口芯片,它们控制接口卡进行工作
  2. 主板上的接口芯片,CPU通过它们对部分外设进行访问
  3. 其他芯片,用来存储相关系统信息,或进行相关的输入输出处理

在这些芯片中,都 有一组可以由CPU读写的寄存器,在物理上,它们可能处于不同的芯片中,但是在以下两点上相同:

  1. 都和CPU的总线相连,
  2. CPU对它们进行或写的进候都通过控制线向它们所在的芯片发出端口读写命令

从CPU角度来说,CPU把这些寄存器都当作端口,对它们进行了统一编址,建立了一个统一的地址空间。每一个端口在地址空间中都有一个地址。

CPU可以直接读写以下3个地方的数据:

  1. CPU内部的寄存器
  2. 内存单元
  3. 端口

端口的读写

端口和内存地址一样,都通过地址总线来传送。在PC系统中,CPU最多可以定位64KB个不同的端口。则端口的地址范围为0~65535

  • 读端口

    in al, 60h
    

    从60h号端口读入一个字节

  • 写端口

    out 60h, al
    

    往60h号端口写入一个字节

    可见这两个指令与其它的指令一样,将最终的目地的紧跟在指令的后面。比如读,读到哪里?读到al。写,写到哪里?写到60h。

    in和out指令只能用al和ax来操作,前者8位,后者16位。

CMOS RAM芯片

在这里插入图片描述

检测点14.1

shl和shr指令

shl左移

shr右移

位移最后移出的一位写入CF中,低位用0补充

mov al, 01001000b
shl al, 1 ;左移一位

如果移动的位数大于1,将1换成cl。

mov al, 01010001b
mov cl, 3
shl al, cl

执行后:al = 10001000b

检测点14.2

CMOS RAM中存储的时间信息

在这里插入图片描述

assume cs:code

data segment        
    db '/','/',' ',':',':'
data ends

code segment

date: db 9, 8, 7, 4, 2, 0

    start:
            mov cx, offset start - offset date ;共6个内容

            mov bx, offset date
            mov di, 160*14

            mov si, 0
            mov ax, data 
            mov ds, ax
        s:  
            mov al, cs:[bx]
            call invoke
            inc bx
            loop s
            
            mov ax, 4c00h
            int 21h
    invoke:
            push cx
            push ax
            push bx

            out 70h, al
            in al, 71h

            mov ah, al ;将8位值给ah
            mov cl, 4 
            shr ah, cl ;右移4位
            and al, 00001111b ;高位置0

            add ah, 30h
            add al, 30h ;加上48(30h)就是对应的数字的ASCII码

            mov bx, 0b800h
            mov es, bx
            mov byte ptr es:[di], ah ;十位
            inc di
            mov byte ptr es:[di], 02 ;颜色
            inc di
            mov byte ptr es:[di], al ;个位
            inc di
            mov byte ptr es:[di], 02
            inc di
;填符号
            mov dl, ds:[si]
            mov byte ptr es:[di], dl
            inc di
            mov byte ptr es:[di], 02
            inc di

            inc si

            pop bx
            pop ax
            pop cx
            ret

code ends
end start

重点BCD码的转换:

两个BCD码是一个字节,高位是高位数据,低位是低位数据。比如:不超过两位的十进制数,用BCD码来表示十位用高四位,个位用低四位。

mov ah, al
mov cl, 4
shr ah, cl ;执行完al的高四位在ah的低四位
and al, 00001111b
assume cs:code

stack segment
    db 128 dup(0)
stack ends

data segment
    dw 0, 0
data ends

code segment

    start:
            mov ax, stack
            mov ss, ax
            mov sp, 128

            mov ax, data
            mov ds, ax
            
            mov ax, 0
            mov es, ax

            push es:[9*4]
            pop ds:[0]
            push es:[9*4+2]
            pop ds:[2] ;保存9号中断

            mov word ptr es:[9*4], offset int9
            mov es:[9*4+2], cs ;更改向量表

          ;显示程序
            mov ax, 0b800h 
            mov es, ax
            mov ah, 'a'
        s:  
            mov  es:[160*12+40*2], ah
            call delay
            inc ah
            cmp ah, 'z'
            jna s

            mov ax, 0
            mov es, ax

          ;向量表归位  
            push ds:[0]
            pop es:[9*4]
            push ds:[2]
            pop es:[9*4+2]

            mov ax, 4c00h
            int 21h

          ;延时程序,根据自己CPU来确定循环次数
     delay: 
            push ax
            push dx
            mov dx, 5h
            mov ax, 0
        s1: 
            sub ax, 1
            sbb dx, 0
            cmp ax, 0
            jne s1
            cmp dx, 0
            jne s1

            pop dx
            pop ax
            ret
          ;更新的9号中断
      int9:
            push ax
            push bx
            push es

            in al, 60h ;读取端口数据

          ;模拟int,因为int9在向量表中变成别的,原来的在ds[2]:ds[0]中
            pushf
            pushf
            pop bx
            and bh, 11111100b
            push bx
            popf
            call dword ptr ds:[0]

          ;是1就改变颜色,不是就跳出
            cmp al, 1
            jne int9ret
            mov ax, 0b800h
            mov es, ax
            inc byte ptr es:[160*12+40*2+1]

    int9ret:
            pop es
            pop bx
            pop ax
            iret
           
code ends
end start

实验14访问CMOS RAM

第15章:外中断

CPU除了可以执行指令外,还可以对外部设备进行控制,接收输入,进行输出。

比如, 按下键盘上的一个键,CPU最终要处理这个键,在使用编辑器时,按下键后,对应键上的内容会显示在显示器上。

接口芯片和端口

外设的输入不直接送入内存和CPU,而是送入相关的接口芯片的端口中,CPU向外设的输出也不是直接送入外设,而是先送入端口中,再由相关的芯片送到外设。

端口在CPU传送过程中起到一个桥梁的作用。

外中断信息

外设的输入随时都有可能发生,CPU怎么及进知道并作出相应的处理呢?

CPU用中断实现了这种可能,原理上等同于原先的内中断, 但是这个中断信息是由外部产生的。

1. 可屏蔽中断

可屏蔽意味着有两种选择:

  • IF = 1,响应中断
  • IF = 0, 不响应中断

可屏蔽信息来自于CPU外部,中断类型码通过数据总线送入CPU。

sti,设置IF = 1

cli,设置IF = 0

IF置0的作用不言而喻,在进入中断处理程序后,禁止其他可屏蔽中断。

2. 不可屏蔽中断

是CPU必须响应的中断,CPU执行完当前指令后,立即响应,引发中断过程。

对于8086CPU中断类型码是固定的2,所以中断过程中, 不需要取中断类型码。

几乎所有处设引发的中断都是可屏蔽中断。

PC机键盘的处理过程

1. 键盘输入

键盘上的每一个键都相当于一个开发,键盘中会有一个芯片对键盘上每一个键的开关状态进行扫描。当你按下一个键或松开一个键时都会产生一个扫描码,然后扫描码被送入相关接口芯片的寄存器中,该寄存器的端口地址为60h。

按下一个键产生的扫描码称为通码

松开一个键产生的扫描码称为断码

扫描码的长度为一个字节,通码的第7位为0,断码的第7位为1

所以它们之间相差2^7。也就是80h。

断码 = 通码 + 80h

2. 引发9号中断
3. 执行9号中断例程

BIOS提供了int 9中断例程

在这里插入图片描述

编写int 9中断例程
  1. 键盘产生扫描码
  2. 扫描码送入60上端口
  3. 引发9号中断
  4. 执行int 9中断例程处理键盘输入

1,2, 3步都是由硬件完成。所以只能改变第4步的中断处理程序。

assume cs:code

stack segment
    db 128 dup(0)
stack ends

data segment
    dw 0, 0
data ends

code segment

    start:
            mov ax, stack
            mov ss, ax
            mov sp, 128

            mov ax, data
            mov ds, ax
            
            mov ax, 0
            mov es, ax

            push es:[9*4]
            pop ds:[0]
            push es:[9*4+2]
            pop ds:[2] ;保存9号中断

            cli
            mov word ptr es:[9*4], offset int9
            mov es:[9*4+2], cs ;更改向量表,设置int 9中断例程的段地址和偏移地址
            sti

          ;显示程序
            mov ax, 0b800h 
            mov es, ax
            mov ah, 'a'
        s:  
            mov  es:[160*12+40*2], ah
            call delay
            inc ah
            cmp ah, 'z'
            jna s

            mov ax, 0
            mov es, ax

            cli
          ;向量表归位  
            push ds:[0]
            pop es:[9*4]
            push ds:[2]
            pop es:[9*4+2]
            sti

            mov ax, 4c00h
            int 21h

          ;延时程序,根据自己CPU来确定循环次数
     delay: 
            push ax
            push dx
            mov dx, 5h
            mov ax, 0
            ;循环50000h次
        s1: 
            sub ax, 1
            sbb dx, 0
            cmp ax, 0
            jne s1
            cmp dx, 0
            jne s1

            pop dx
            pop ax
            ret
          ;更新的9号中断
      int9:
            push ax
            push bx
            push es

            in al, 60h ;读取端口数据

            pushf
            call dword ptr ds:[0]

          ;是1就改变颜色,不是就跳出
            cmp al, 1
            jne int9ret
            mov ax, 0b800h
            mov es, ax
            inc byte ptr es:[160*12+40*2+1]

    int9ret:
            pop es
            pop bx
            pop ax
            iret
           
code ends
end start

改变中断的我们能做的就只是改变它的向量表。也可以用模拟的手段模拟一个中断。

实验15安装新的int9中断例程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CCPigSnail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值