汇编原理自我总结(四)

汇编原理自我总结(四)

第十三章 int指令

13.1 int 指令

int指令的格式:int n(n为中断码),供能是引发中断过程。

执行过程如下:

  1. 取中断类型码n;
  2. 标志寄存器入栈,TF = 0,IF = 0;
  3. CS,IP入栈;
  4. (IP)=(n*4),(CS)= (n*4+2);

从此处转去执行n号中断处理程序。

编程的时候,可以用int指令调用这些处理程序,这些处理程序之后叫中断例程。

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

编程1:编写,安装中断7ch的中断例程。

功能:求一word型数据的平方

参数:ax

结果:dx,ax中分别存放高位和低位

assume cs:code
code segment
start:
	;安装
	mov ax,cs
	mov ds,ax
	mov si,offset sqr
	
	mov ax,0
	mov es,ax
	mov di,0200h
	
	mov cx,offset sqrend-offset sqr
	cld
	rep movsb
	
	;中断向量表
	mov ax,0
	mov es,ax
	mov word ptr es:[7cH*4],0
	mov word ptr es:[7ch*4+2],0200h
	mov ax,4c00h
	int 21h
	
sqr:
	mul ax
	iret
sqrend:
	nop
	
code ends
end start

编写2:编写,安装7ch的中断例程

功能:将一个全是字母,以0为结尾的字符串转化为大写字母。

参数:ds:si指向字符串的首地址

assume cs:code
data segment
	db 'conversation',0
data ends
code segment
start:
	;安装
	mov ax,cs
	mov ds,ax
	mov si,offset conversation
	
	mov ax,0
	mov es,ax
	mov di,0200h
	
	mov cx,offset conversationend-offset conversation
	cld
	rep movsb
	
	mov ax,0
	mov es,ax
	mov word ptr es:[7ch*4],0
	mov word ptr es:[7ch*4+2],0200h
	mov ax,4c00h
	int 21h
conversation:
	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
conversationend:
	nop
	
	code ends
	end start

13.3 对int,iret和栈的深入理解

问题:用7ch中断例程完成loop指令的功能。

参数:ax,次数;dx,位移;

应用举例:

assume cs:code
code segment
start:
		mov ax,0b800h
		mov es,ax
		mov di,160*12
		
		mov bx,offset s-offset se
		mov cx,80
	s:
		mov byte ptr es:[di],'!'
		add di,2
		int 7ch
	se:	nop
	
		mov ax,4c00h
		int 21h
		code ends
		
	end start
lp: push bp
	mov bp,sp
	dec cx
	jcxz lpret
	add [bp+2],bx
lpret:
	pop bp
	iret

用7ch中断例程完成jmp near ptr s指令的功能,用bx向中断例程传送转移位移。

应用举例:在屏幕的前12行,显示data段中以0结尾的字符串。

assume cs:code
data segment
	db 'conversation',0
data ends
code segment
start:
	mov ax,data
	mov ds,ax
	mov si,0
	mov ax,0b800h
	mov es,ax
	mov di,12*160
s:	cmp byte ptr [si],0
	je ok
	mov al,[si]
	mov es:[di],al
	inc si
	add di,2
	mov bx,offset s-offset ok
	int 7ch
ok:	mov ax,4c00h
	int 21h
	code ends
	end start
jnmp:
	push bp
	mov bp,sp
	cmp bx,0
	jna jnmp1
	add [bp],bx
	pop bp
	iret
jnmp1:
	sub [bx],bx
	pop bp
	iret

13.4 BIOS和DOS所提供的中断例程

在系统板的ROM中存放着一套程序,称为BIOS(Basic Input/Output System),包含以下几部分内容:

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

操作系统DOS也提供了中断例程,从操作系统的角度来看,DOS的中断例程就是系统向程序员提供的编程资源。

和硬件设备相关的DOS中断例程中,一般都调用了BIOS的中断例程。

13.5 BIOS和DOS中断例程的安装过程

  1. 开机后,CPU一加电,初始化(CS)= 0ffffh,(IP)= 0,自动从FFFF:0单元开始执行程序。FFFF:0处有一条转跳指令,CPU执行该指令后,转去执行BIOS中硬件系统检测和初始化程序。
  2. 初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。注意,对于BIOS所提供的中断例程,只需将入口地址登记在中断向量表中即可,因为它们是固化到ROM中的程序,一直在内存中存在。
  3. 硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。从此将计算机交由操作系统控制。
  4. DOS启动后,除完成其他工作外,还将它提供的中断例程装入内存,并建立相应的中断向量。

13.6 BIOS中断例程应用

int 10h:一般来说,一个供程序员调用的中断例程中往往包括多个子程序,中段例程内部用传递进来的参数来决定执行哪一个子程序。BIOS和DOS提供的中断例程,都用ah来传递内部子程序的编号。

assume cs:code
code segment

mov ah,2      ;置光标
mov bh,0		;第0页
mov dh,5         ;dh中放行号
mov dl,12      ;dl中放列号
int 10h

mov ah,9        ;在光标位置显示字符
mov al,'a'       ;字符
mov bl,11001010b  ;颜色属性
mov bh,0           ;第0页
mov cx,3              
int 10h

mov ax,4c00h
int 21h

code ends
end

13.7 DOS中断例程应用

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

程序返回功能:

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

显示字符串功能:

ds:dx 指向字符串 ;要显示的字符串需用”$“作为结束符
mov ah,9 ;功能号9,表示在光标位置显示字符串
int 21h

assume cs:code

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

实验十三

  1. 编写安装 int 7ch 中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。

    参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si指向字符串首地址。

    assume cs:code
    data segment
    start:
    	mov ax,cs
    	mov ds,ax
    	mov si,offset show
    	
    	mov ax,0
    	mov es,ax
    	mov di,0200h
    	
    	mov cx,offset showend-offset show
    	
    	cld
    	rep movsb
    	
    	mov ax,0
    	mov es,ax
    	mov es:[7ch*4],0200h
    	mov es:[7ch*4+2],0
    	mov ax,4c00h
    	int 21h
    	
    show:
    	mov ax,0b800h
    	mov es,ax
    	mov al,dh
    	mov dh,160
    	mul dh
    	add ax,2*dl
    	mov di,ax
    	
    	mov al,cl
    s:
    	mov cl,[si]
    	mov ch,0
    	jcxz ok
    	mov es:[di],cl
    	inc di
    	mov es:[di],al
    	inc di
    	inc si
    	jmp short s
    
    ok:
    	iret
    
    showend:
    	nop
    	code ends
    	end start
    

    测试:

    assume cs:code
    data segment
    	db 'welcome to masm!',0
    data ends
    code segment
    start:
    	mov dh,10
    	mov dl,10
    	mov cl.2
    	mov ax,data
    	mov ds,ax
    	mov si,0
    	int 7ch
    	mov ax,4c00h
    	int 21h
    	code ends
    	end start
    
  2. 编写并安装int 7ch中断例程,功能为完成loop指令的功能。

    参数:(cx)=循环次数,(bx)=位移。

    assume cs:code
    code segment
    start:
    	mov ax,cs
    	mov ds,ax
    	mov si,offset lp
    	
    	mov ax,0
    	mov es,ax
    	mov di,0200h
    	
    	mov cx,offset lpend-offset lp
    	cld
    	rep movsb
    	
    	mov ax,0
    	mov es,ax
    	mov word ptr es[7ch*4],0200h
    	mov word ptr es[7ch*4+2],0
    	
    	mov ax,4c00h
    	int 21h
    	
    lp:	push bp
    	
    	mov bp,sp
    	dec cx
    	jcxz ok
    	add [bp+2],bx
    
    ok:	pop bp
    	iret
    
    lpend:nop
    code ends
    end start
    

    测验:

    assume cs:code
    code segment
    start:
    	mov ax,0b800h
    	mov es,ax
    	mov di,160*12
    	mov bx,offset s-offset se
    	mov cx,80
    	s:
    	mov byte ptr es:[di],'!'
    	add di,2
    	int 7ch
    	se:nop 
    	mov ax,4c00h
    	int 21h
    	code ends
    	end start
    
  3. 补全程序,分别在屏幕的第2、4、6、8行显示4句英文诗。

    assume cs:code
    code segment
    s1: db 'Good,better,best,',','$'
    s2: db 'Never let it rest,',','$'
    s3: db 'Till good is better,',',','$'
    s4: db 'And better,best.',',','$'
    s: dw offset s1,offset s2,offset s3,offset s4
    row: db 2,4,6,8
    
    start:
    	mov ax,cs
    	mov ds.ax
    	mov bx,offset s
    	mov si,offset row
    	mov cx,4
    ok:
    	mov bh,0
    	mov dh,ds:[si]            ;
    	mov dl,0
    	mov ah,2
    	int 10h
    	
    	mov dx,ds:[bx]           ;
    	mov ah,9
    	int 21h
    	add bx,2                 ;
    	inc si                    ;
    	loop ok
    	
    	mov ax,4c00h
    	int 21h
    code ends
    end start
    

    第十四章 端口

    在PC机系统中,和CPU通过总线相连的芯片除存储器外,还有以下3种芯片:

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

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

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

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

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

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

14.1 端口的读写

在访问端口的时候,CPU通过地址来定位端口。因为端口所在的芯片和CPU通过总线相连,所以,端口地址和内存地址一样,通过地址总线来传送。在PC系统中,CPU最多可以定位64KB个不同的端口。则端口地址范围为0~65535。

对端口的读写不能用mov 、push、pop等内存读写命令。端口的读写只有两条:in和out,分别用于从端口读取数据和往端口写入数据。

访问端口:

in al,60h ;从60h号端口读入一个字节

执行时与总线相关的操作如下。

  1. CPU通过地址线将地址信息60h发出;
  2. CPU通过控制线发出端口读命令,选中端口所在的芯片,并通知它,将要从中读取数据;
  3. 端口所在的芯片将60h端口中的数据通过数据线送入CPU。

注意,在in和out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据。访问8位端口时用al,访问16位端口时用ax。

对0~255以内的端口进行读写时:

int al,20h

out 20h,al

对256~65535的端口进行读写时,端口号放在dx中:

mov dx,3f8h

in al,dx

out dx,al

14.2 CMOS RAM芯片

该芯片的特征如下:

  1. 包含一个实时钟和一个有128个存储单元的RAM存储器(早期的计算机为64个字节)。
  2. 该芯片靠电池供电。所以,关机后其内部的实时钟仍可正常工作,RAM中的信息不丢失。
  3. 128个字节的RAM中,内部实时钟占用0~0dh单元来保存时间信息,其余大部分单元用于保存系统配置信息。供系统启动时BIOS程序读取。BIOS也提供了相关的程序,使我们可以在开机的时候配置CMOS RAM中的系统信息。
  4. 该芯片内部有两个端口,端口地址为70h和71h。CPU通过这两个端口来读写CMOS RAM。
  5. 70h为地址端口,存放要访问的CMOS RAM单元的地址;71h为数据端口,存放从选定的CMOS RAM单元中读取的数据,或要写入到其中的数据。可见,CPU对CMOS RAM的读写分两步进行,比如,读CMOS RAM的2号单元:

将2送入端口70h;

从端口71h读出2号单元的内容

14.3 shl和shr指令

逻辑移位指令。shl:逻辑左移指令:

  1. 将一个寄存器或内存单元中的数据向左移位;
  2. 将最后移出的一位写入CF中;
  3. 最低位用0补充。

指令:

mov al,01001000b

shl al,1 ;将al中的数据左移一位

执行后,(al)=10010000b,CF=0。

如果移动位数大于1时,必须将移动位数放在cl中。

mov al,01010001b

mov cl,3

shl al,cl

shr是逻辑右移指令,它和shl所进行的操作刚好相反。右移一位空出来的位用0填充,逻辑右移嘛。算术右移是用最高位填充。

mov al,10000001b

shr al,1

执行后,(al)=0100000b,CF=1。

编程:用加法和移位指令计算(ax)=(ax)*10。

assume cs:code
code segment
start:
	mov ax,520h
	mov dx,ax
	shl ax,1
	mov cl,3
	shl dx,cl
	add ax,dx;(ax)*10 = (ax)*2+(ax)*8
	
	mov ax,4c00h
	int 21h
	code ends
	end start

14.4 CMOS RAM中存储的时间信息

在CMOS RAM中,存放着当前的时间:年、月、日、时、分、秒。这6个信息的长度都为1个字节,存放单元为:

秒:0 分:2 时:4 日:7 月:8 年:9

这些数据以BCD码的方式存放。

10: 0 1 2 3 4 5 6 7 8 9

BCD码:0000 0001 0010 0011 0100 0101 0110 0111 1000 1001

数值26的BCD码为:0010 0110。

一个字节可表示两个bcd码。则CMOS RAM存储时间信息的单元中,存储了用两个BCD码表示的十进制数,高4位的BCD码表示十位,低4位的表示个位。比如:00010100b表示14。

编程,在屏幕中间显示当前的月份。

assume cs:code
code segment
start:
	mov al,8
	out 70h,al
	in al,71h
	
	mov ah,al
	mov cl,4
	shr ah,cl
	and al,00001111b
	
	add al,30h
	add ah,30h
	
	mov bx,0b800h
	mov es,bx
	mov byte ptr es:[160*12+40*2],ah
	mov byte ptr es:[160*12+40*2+2],al
	
	mov ax,4c00h
	int 21h
	
	code ends
end start

实验十四

编程,以“年/月/日 时:分:秒”的格式,显示当前的日期、时间。

assume cs:code
stack segment
	db 16 dup (0)
stack ends
code segment
start:
	mov ax,0b800h
	mov es,ax
	mov si,160*12+33*2
	
	mov ax,9
	mov cx,3
s:
	push cx
	push ax
	out 70h,al
	in al,71h
	
	mov ah,al
	mov cl,4
	shr ah,cl
	and al,00001111b

	add ah,30h
	add al,30h
	
	mov es:[si],ah
	add si,2
	mov es:[si],al
	add si,2

	pop ax
	pop cx
	cmp ax,7
	je over
	mov byte ptr es:[si],'/'
	add si,2
	sub ax,1
	loop s
	
over:
	mov byte ptr es:[si],' '
	add si,2

	mov cx,3
	mov ax,4
s0:
	push cx
	push ax
	mov dx,cx
	out 70h,al
	in al,71h
	
	mov ah,al
	mov cx,4
	shr ah,cl
	and al,00001111b

	add ah,30h
	add al,30h
	
	mov es:[si],ah
	add si,2
	mov es:[si],al
	add si,2
	pop ax
	pop cx
	cmp ax,0
	je over0
	mov byte ptr es:[si],':'
	add si,2
	sub ax,2
	loop s0
over0:
	mov ax,4c00h
	int 21h
	code ends
end start

第十五章 外中断

要及时处理外设的输入,就要解决两个问题:外设的输入随时可能发生,CPU如何得知?CPU从何处得到外设的输入?

15.1 接口芯片和端口

外设的输入与输出(诸如CPU的控制信息)不直接送入内存和CPU,而是送入相应的接口芯片的端口中;CPU的输入与输出也是送到该芯片的端口中。

可见,CPU通过端口和外部设备进行联系。

15.2 外中断信息

CPU如何知道外设随时可能发给它的信息呢?提供中断机制来满足这种需要。这种中断信息来自外部,由相关的芯片给向CPU发出相应的中断信息。CPU在执行完当前的指令后,可以检测到发送过来的中断信息,引发中断过程,处理外设的输入。

在PC系统中,外中断源一共有以下两类:

  1. 可屏蔽中断
  2. 不可屏蔽中断

可屏蔽中断是CPU可以不响应的外中断,具体响应与否要看标志寄存器·的IF位的设置,当CPU检测到可屏蔽中断信息时,如果IF=1,则CPU在执行完当前指令后响应中断,引发中断过程;如果IF=0,则不响应可屏蔽中断。

可屏蔽中断所引发的中断过程,除了在取得中断码的实现上有所不同外,基本上和内中断的中断过程相同。外部中断的中断码通过数据总线送入CPU;而内中断的中断类型码是在CPU内部产生的。

在中断过程中将IF设置为0的原因就是在进入中断处理程序后,禁止其他的可屏蔽中断。

当然,如果在处理程序中需要处理可屏蔽中断,可以用指令将IF置1。8086CPU提供的设置IF的指令如下:

sti ;设置IF=1

cli ;设置IF=0

不可屏蔽中断是CPU必须响应的外中断。当检测到此类中断信息时,则在执行完当前指令后,立即响应,引发中断过程。

对于8086CPU,不可中断的中断类型码固定为2,所以中断过程中,不需要取中断类型码。则不可屏蔽中断的中断过程为:

  1. 标志寄存器入栈,IF=0,IF=0;
  2. CS、IP入栈;
  3. (IP)=(8),(CS)=(0AH)。

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

15.3 PC机键盘的处理过程

键盘输入: 键盘上的每一个键相当于一个开关,键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描。

按下一个键时,开关接通,该芯片产生一个扫描码,说明了按下的键的位置,扫描码被送入主板上相关接口芯片的寄存器中,该寄存器的端口地址为60h。这个扫描码被称为通码。

松开按下的键时,产生断码,也被送入相同的端口地址中。

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

断码 = 通码 + 80h

在这里插入图片描述

在这里插入图片描述
引发9号中断: 键盘的输入到达60h端口时,芯片向CPU发出中断类型码为9的中断信息。CPU检测中断信息后,看IF的值,是否响应。若响应,执行int 9中断例程。

执行int 9中断例程: 由BIOS提供int 9中断例程,用来进行基本的键盘输入处理,主要的工作如下:

  1. 读出60h端口的扫描码;
  2. 如果是字符键的扫描码,将该码和它所对应的字符码(ASCII码)送入内存中的BIOS键盘缓冲区;如果是控制键(如Ctrl)和切换键(如CapsLock)的码,则将其转变为状态字节写入内存中存储状态字节的单元;
  3. 对键盘系统进行相关的控制,比如,向相关芯片发出应答信息。

BIOS键盘缓冲区是系统启动后,BIOS用于存放int 9中断例程所接收的键盘输入的内存区。该内存区可以存储15个键盘输入,因为int 9中断例程除了接收扫描码外,还要产生和码对应的字符码,所以在BIOS键盘缓冲区中,一个键盘输入用一个字单元存放,高位字节存放扫描码,低位字节存放字符码。

0040:17单元存储键盘状态字节,记录了控制键和切换键的状态。

在这里插入图片描述

15.4 编写int 9中断例程

编程:在屏幕中间依次显示“a"~“z”,并可以让人看清,在显示的过程中,按下Esc键后。改变显示的颜色。

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]    ;将原来的int 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,4c00h
	int 21h
	
delay:
	push ax
	push dx
	
	mov dx,10h
	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
	
	;---------------以下为新的int 9中断例程-----------------
	int9:
	push ax
	push bx
	push es
	
	int al,60h
	
	pushf
	;pushf
	;pop bx
	;and bh,11111100b
	;push bx
	;popf
	call dword ptr ds:[0]
	
	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.5 安装新的int 9中断例程

任务:安装一个新的int 9中断例程。

功能:在DOS下,按F1键后改变当前屏幕的显示颜色。

assume cs:code
stack segment
	db 128 dup (0)
stack ends

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

	mov ax,0
	mov ds,ax

	push ds:[9*4]
	pop ds:[200h]

	push ds:[9*4+2]
	pop ds:[202h]
;安装
	mov ax,cs
	mov ds,ax
	mov si,offset int9

	mov ax,0
	mov es,ax
	mov di,204h

	mov cx,offset int9end-offset int9

	cld
	rep movsb

	cli
	mov word ptr es:[9*4],204h
	mov word ptr es:[9*4+2],0
	sti

	mov ax,4c00h
	int 21h

int9:	
	
	push ax
	push es
	push bx
	push cx

	mov ax,0
	mov ds,ax

	in al,60h

	pushf
	call dword ptr ds:[200h]

	cmp al,3bh
	jne int9over

	mov ax,0b800h
	mov es,ax
	mov bx,1
	mov cx,2000
s:
	inc byte ptr es:[bx]
	add bx,2
	loop s

int9over:
	pop cx
	pop bx
	pop es
	pop ax
	iret

int9end:
	nop
	code ends
	end start


et:
	pop es
	pop bx
	pop ax
	iret
	
	code ends
end start
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值