《汇编语言》王爽(第四版) 第十三章 检测点13.1

文章目录

前言

一、7CH中断例程的安装

二、编写7CH中断例程

1.实现loop指令的功能

(1)先放上代码

(2)接下来分析

2.实现jmp near ptr s指令的功能

(1)实验任务

(2)实现功能

总结


前言

本文是王爽老师《汇编语言》(第四版) 第十三章 检测点13.1 使用7CH中断例程实现loop指令功能与jmp near ptr s指令功能 的分析及代码。

一、7CH中断例程的安装

这个检测点的两个任务,都与7CH中断例程有关。要实现这些功能,首先需要写一个通用的7CH中断例程的安装程序。这与上一篇写过的实验12中的安装程序几乎是一样的,只不过这次用一个install子程序封装了。代码如下。

assume cs:code
code segment
start:  ;第13章检测点13.1
    
    call install    ;安装7CH中断例程

    int 7CH        ;调用7CH中断例程

    mov ax,4c00H
    int 21H
install:    ;功能:将7CH中断例程安装在0:200H处
        ;参数:无
        ;返回:无

    push ax
    push ds 
    push si
    push es 
    push di 
    push cx

    ;将7CH中断例程(即do7c)复制到0:200H处

    mov ax,cs       ;设置源地址的段地址
    mov ds,ax
    mov si,offset do7c     ;设置源地址的偏移地址

    mov ax,0        ;设置目标地址的段地址
    mov es,ax
    mov di,200H     ;设置目标地址的偏移地址

    mov cx,offset do7cend - offset do7c     ;设置复制长度
    cld             ;设置DF标志位为0,正向传送
    rep movsb       ;循环传送数据

    ;设置中断向量表
    
    mov ax,0        ;设置ds指向7CH中断例程的段地址存储地址
    mov ds,ax
    mov si,7cH*4    ;设置si指向7CH中断例程的偏移地址存储地址

    mov ds:[si],200H    ;将7CH中断例程的偏移地址存入中断向量表
    mov ds:[si+2],0     ;将7CH中断例程的段地址存入中断向量表
    
    pop cx
    pop di
    pop es
    pop si
    pop ds
    pop ax

    ret 

    ;7CH中断例程如下

do7c:   ;do7c中断例程
    
    ;随便写的一段测试代码,效果是在屏幕中显示一个绿色的字符A
    push ax     
    push es
    mov ax,0B800H
    mov es,ax
    mov es:[2152],0241H
    pop es
    pop ax

    iret
do7cend:nop 

code ends
end start

二、编写7CH中断例程

接下来,完成两个检测点中的功能。

1.实现loop指令的功能

(1)先放上代码

assume cs:code
code segment
start:  ;第13章 检测点13.1(1) 实现loop指令的功能
    
    call install    ;安装7CH中断例程

    mov ax,0B800H       ;设置es:di指向显存区显示地址
    mov es,ax
    mov di,160*12

    mov bx,offset s-offset se   ;bx是标号se到标号s的转移位移
    mov cx,80           ;循环次数

    s:
    mov byte ptr es:[di],'!'
    add di,2
    int 7cH     ;调用7CH中断例程,实现loop指令的功能
    se:nop

    mov ax,4c00H
    int 21H
install:    ;功能:将7CH中断例程安装在0:200H处
        ;参数:无
        ;返回:无

    push ax
    push ds 
    push si
    push es 
    push di 
    push cx

    ;将7CH中断例程(即do7c)复制到0:200H处

    mov ax,cs       ;设置源地址的段地址
    mov ds,ax
    mov si,offset do7c     ;设置源地址的偏移地址

    mov ax,0        ;设置目标地址的段地址
    mov es,ax
    mov di,200H     ;设置目标地址的偏移地址

    mov cx,offset do7cend - offset do7c     ;设置复制长度
    cld             ;设置DF标志位为0,正向传送
    rep movsb       ;循环传送数据

    ;设置中断向量表
    
    mov ax,0        ;设置ds指向7CH中断例程的段地址存储地址
    mov ds,ax
    mov si,7cH*4    ;设置si指向7CH中断例程的偏移地址存储地址

    mov ds:[si],200H    ;将7CH中断例程的偏移地址存入中断向量表
    mov ds:[si+2],0     ;将7CH中断例程的段地址存入中断向量表
    
    pop cx
    pop di
    pop es
    pop si
    pop ds
    pop ax

    ret 

    ;7CH中断例程如下

do7c:   ;功能:loop指令
        ;参数:cx是循环次数
        ;       bx是转移位移
        ;返回:无

    ;在调用中断例程前,CPU已经依次将flag、cs、ip压入栈
    push bp     ;这个中断例程中用到bp,压入栈暂存
    mov bp,sp   ;
    dec cx      ;实现cx-1的功能
    jcxz do7c_ok    ;若cx≠0,则跳转完成循环,否则什么也不做
    add [bp+2],bx   ;将栈中存放的调用程序的IP,修改为转移后后的IP
    do7c_ok:
    pop bp

    iret        ;将ip、cs、flag依次pop出栈
do7cend:nop 
    
code ends
end start

(2)接下来分析

这个中断例程中所能进行的最大转移位移,关键代码就是下面这一条。

add [bp+2],bx

[bp+2]是栈中存放的调用程序的IP,bx是调用程序传入的参数,表示转移位移。这里的bx理论上可以最大可以支持FFFFH;经过实践检验,若bx=FFFFH ,这个中断例程也可以正常运行。代码如下。

结论:这个中断例程能进行的最大转移位移是FFFFH,也就是 -32768-32767 。

do7c:   ;功能:loop指令
        ;参数:cx是循环次数
        ;       bx是转移位移
        ;返回:无

    mov bx,0FFFFH    ;测试bx的最大值

    push bp     ;这个中断例程中用到bp,压入栈暂存
    mov bp,sp   ;
    dec cx      ;实现cx-1的功能
    jcxz do7c_ok    ;若cx≠0,则跳转完成循环,否则什么也不做
    add [bp+2],bx   ;将栈中存放的调用程序的IP,修改为转移后后的IP
    do7c_ok:
    pop bp

    iret        ;将ip、cs、flag依次pop出栈
do7cend:nop 

2.实现jmp near ptr s指令的功能

(1)实验任务

实验任务:用7CH中断例程完成jmp near ptr s指令的功能,用bx向中断例程传送转移位移。

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

代码如下。

assume cs:code
data segment
    db 'conversation',0
data ends

code segment
start:  ;第13章 检测点13.1(2) 实现jmp near ptr s指令的功能
    
    call install    ;安装7CH中断例程

    mov ax,data     ;设置ds:si指向源地址
    mov ds,ax
    mov si,0

    mov ax,0B800H   ;设置es:di指向显存目标地址
    mov es,ax
    mov di,160*12

    s:              ;循环传送每个字符
    cmp byte ptr ds:[si],0
    je ok
    mov al,ds:[si]
    mov es:[di],al
    inc si
    add di,2
    
    mov bx,offset s-offset ok   ;设置bx为转移位置=标号ok至标号s的转移位移
    int 7CH         ;功能相当于: jmp near ptr s
    
    ok:

    mov ax,4c00H
    int 21H
    
code ends
end start

(2)实现功能

首先分析一下,jmp near ptr s实现的是近转移,转移位移不超过FFFFH,正好用16位的bx来存放。

要实现跳转,就要对栈中存储的调用程序的IP进行修改。代码如下。

do7c:   ;功能:实现jmp near ptr s指令
        ;参数:bx是转移位移
        ;返回:无

    ;在调用中断例程前,CPU已经依次将flag、cs、ip压入栈
   
    push bp
    mov bp,sp
    add ss:[bp+2],bx
    pop bp

    iret    ;将ip、cs、flag依次pop出栈
do7cend:nop 

这与第一个实验任务(实现loop指令)的中断例程很相似,只是更简单一些(不用判断cx是否等于0)。注意使用bp寄存器要push和pop,以及注意[bp+2]是栈中存放的IP的值。

效果如下。


总结

本文是王爽老师《汇编语言》(第四版) 第十三章 检测点13.1 使用7CH中断例程实现loop指令功能与jmp near ptr s指令功能 的分析及代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值