汇编语言 第16章 实验16 要点总结

文章讲述了作者在汇编语言实验中遇到的问题,即代码复制后直接定址表中的地址不正确。通过问题分析和调试,发现是由于标号编译后的地址与实际目标地址冲突。解决方案是使用`org`指令调整代码起始位置,确保复制后的代码地址正确性。
摘要由CSDN通过智能技术生成

目录

0. 前言

1. 实验基础

2. 发现问题

3. 问题分析

4. 调试排查

5. 解决方案

6. 要点总结


0. 前言

  • 参考材料:《汇编语言》(第4版)王爽 第16章 直接定址表

在做这个实验的时候,笔者也遇到了一些小问题,现在分享出来,希望对正在学习这一部分内容的朋友有所帮助~


1. 实验基础

  • 阅读第16章,了解直接定址表的使用逻辑

由于书中已经提供了大部分逻辑的代码(参见p296 16.4 程序入口地址的直接定址表),因此这里就不再赘述

根据书中的逻辑很容易写出如下代码👇:

assume cs:code

code segment
; 安装一个新的 int 7ch 中断例程,为显示输出提供如下功能程序。
;(1)清屏;
;(2)设置前景色;
;(3)设置背景色;
;(4)向上滚动一行。
; ah传递功能号:0 表示清屏,1 表示设置前景色,2 表示设置背景色,3 表示向上滚动一行,其它数字正常返回;
; 对于 1、2 号功能,用al传送颜色值,0 <= al <= 7
start:
    ;安装程序
    push cs
    pop ds
    mov si,offset install
    mov ax,0
    mov es,ax
    mov di,200H
    mov cx,offset installend-offset install
    cld
    rep movsb

    ;安全修改向量表
    cli
    mov word ptr es:[7cH*4],200H
    mov word ptr es:[7cH*4+2],0
    sti

    ;安装程序结束
    mov ax,4c00H
    int 21H

;需安装代码段
install:
    jmp short set
    table dw sub0,sub1,sub2,sub3
set:
    push bx
    cmp ah,3
    ja setret
    mov bl,ah
    sub bh,bh
    shl bx,1
    call word ptr table[bx]
setret:
    pop bx
    iret

;(1)清屏
sub0:
    push bx
    push cx
    push es
    mov bx,0b800H
    mov es,bx
    sub bx,bx
    mov cx,2000
sub0s:
    mov byte ptr es:[bx],' '
    add bx,2
    loop sub0s
    pop es
    pop cx
    pop bx
    ret

;(2)设置前景色
sub1:
    push bx
    push cx
    push es
    mov bx,0b800H
    mov es,bx
    mov bx,1
    mov cx,2000
sub1s:
    and byte ptr es:[bx],11111000b
    or es:[bx],al
    add bx,2
    loop sub1s
    pop es
    pop cx
    pop bx
    ret

;(3)设置背景色
sub2:
    push ax
    push bx
    push cx
    push es
    mov bx,0b800H
    mov es,bx
    mov bx,1
    mov cl,4
    shl al,cl
    mov cx,2000
sub2s:
    and byte ptr es:[bx],10001111b
    or es:[bx],al
    add bx,2
    loop sub2s
    pop es
    pop cx
    pop bx
    pop ax
    ret

;(4)向上滚动一行
sub3:
    push bx
    push cx
    push ds
    push es
    push si
    push di

    mov bx,0b800H
    mov ds,bx
    mov es,bx
    mov si,160
    sub di,di
    mov cx,160*24
    rep movsb

    mov cx,80
sub3s:
    mov byte ptr es:[di]," "
    add di,2
    loop sub3s

    pop di
    pop si
    pop es
    pop ds
    pop cx
    pop bx
    ret

;需安装代码段结束
installend:
    nop

code ends
end start

注意:第15章曾提到过如何较为安全地修改向量表,在这里也出现了相应的应用场景

    ;安全修改向量表
    cli
    mov word ptr es:[7cH*4],200H
    mov word ptr es:[7cH*4+2],0
    sti


如果针对这一部分还有不明白的可以看一下我写的上一篇文章:

汇编语言 第15章 外中断 扩编中断例程的设计思路及注意事项(附书上示例及实验代码+注释)-CSDN博客


2. 发现问题

经过测试,我们发现这段安装程序虽然能够正常运行,但是安装过后并不能实现正确的功能

这里提供一个可以对所有输入进行全面测试的程序,供有需要的朋友直接使用:)

注意:测试程序运行时颜色变化较为强烈,建议将屏幕亮度调低后进行测试

assume cs:code

code segment
;对所有输入进行全面测试程序
start:
    ;全屏字符置绿色
    mov ah,1
    mov al,2
    int 7cH
    ;等待一段时间后进行其它测试,下同理
    call delay

    ;全屏向上移动一行
    mov ah,3
    mov al,0
    int 7cH
    call delay

    ;全屏背景置红色
    mov ah,2
    mov al,4
    int 7cH
    call delay

    ;清屏
    mov ah,0
    mov al,0
    int 7cH
    call delay

    ;其它输入测试
    mov ah,4
    mov al,0
    int 7cH
    call delay
    
    ;测试程序结束
    mov ax,4c00H
    int 21H

;延迟方法
delay:
    push ax
    push dx
    mov dx,10H
decrease:
    sub ax,1
    sbb dx,0
    cmp ax,0
    jne decrease
    cmp dx,0
    jne decrease
    pop dx
    pop ax
    ret
code ends
end start


3. 问题分析

  • 在进行调试之前我们可以先思考一下,问题可能发生在哪个环节?

既然书中16.4节类似代码可以正常运行,那么我们需要关注的是实验代码与前者区别在何处。

很明显,我们所写的代码中多了一个安装中断例程的步骤,因此我们基本可以确定,问题基本发生在代码转移,即地址改变的过程中。

  • 结论:调试过程中我们需要重点关注几条涉及数据标号的指令,我们遇到的问题很可能就发生在编译器对标号的编译环节。

4. 调试排查

我们运行安装程序后进入Debug模式进行调试,可以使用上述测试程序进行单步调试(Debug test.exe

于是我们注意到了,这里出现了标号编译,对应代码如下:

    call word ptr table[bx]

此时CS0BX为一个很小的数字,因此CS:BX+2AH显然在0:200H之前,而我们保存的table应当被保存在0:202H处(0:200H处保存了 jmp short set 指令),如下图:

这里我们又发现了一个问题,根据推测这些子程序应当被保存在大于200H的地址处,因此可以判断table中保存的数据不是正确的地址,看来直接修改IP的跳转指令经过编译后的标号被复制后并不总是指向正确的地址


5. 解决方案

  • 现在已经确定了问题所在:table及四个子程序的标号被复制后指向了错误的地址

由于待复制代码最终会被安装到0:200H处,因此我们可以考虑一开始就将这段代码安装到CS:200H处,这样就可以使得标号被编译时与被复制后的IP地址吻合,以此来防止代码复制后造成的地址混乱。

这里我们可以使用 org指令(origin):

;表示从IP为200H处开始存放代码
org 200H
;需安装代码段
install:
    jmp short set
    table dw sub0,sub1,sub2,sub3
set:
    push bx
    cmp ah,3
    ja setret
    mov bl,ah
    sub bh,bh
    shl bx,1
    call word ptr table[bx]
setret:
    pop bx
    iret

这是没有使用指令 org 200H 时的编译结果:

这是使用指令 org 200H 后的编译结果:

修改代码后再次进行测试, 一切运行正常!

再次提醒:测试程序运行时颜色变化较为强烈,建议将屏幕亮度调低后进行测试


6. 要点总结

  • 注意修改向量表时保证安全性
  • 直接修改IP的跳转指令经过编译后的标号被复制后并不总是指向正确的地址,因此当我们需要复制程序时,我们可以通过org指令提前将待复制程序从复制后的IP处开始编译,保证这些经过编译后的常数复制后的正确性
  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值