找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1494|回复: 0

汇编作业 实验16

[复制链接]
  • TA的每日心情
    开心
    2018-10-31 14:26
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    78

    主题

    109

    回帖

    1019

    积分

    高级会员

    积分
    1019

    猴年

    龙龙实名认证 发表于 2015-6-22 03:15:57 | 显示全部楼层 |阅读模式
      这个实验比较有趣,光看书写出来的程序总是运行不正确
      不断调试后才发现原来是在偏移地址的计算中出现了错误
      以下情况是在代码中int 7ch中断例程放在start前讨论的,至于为什么要写在前面,之后说明
      table dw sub1, sub2, sub3, sub4
      这里面sub1,sub2等等的偏移地址在未安装前是相对于代码段即code而言的
      因为编译时程序的偏移地址已经计算好放在table表中,这里JMP指令占3个字节,table占8个字节,所以sub1的偏移地址为000BH,安装后物理地址为0020BH
      如果在安装程序时继续将中断向量表设置为0000H:0200H
      那么问题出来了,假设输入0,table的段地址默认是cs,偏移地址是3,在call word ptr table[bx]时,(table[bx])的实际值,3+0=3,则最终转移的物理地址是(0000H:0003H)=?,显然这和预期中的物理地址(0000H:0203H)=0020BH差得太远
      所以在设置中断向量表时,应该设成0020H:0000H,这样在计算转移地址时算出来的值是(0020H:0003H),和(0000H:0203H)一样
      相信看到这里也就明了了为什么要把中断例程放在start前面,因为容易计算偏移地址来设置中断向量表
      assume cs:code, ss:stack
      ; ****************************************
      ; 堆栈段
      stack segment
      db 128 dup(0)
      stack ends
      ; ****************************************
      ; ****************************************
      ; 代码段
      code segment
      ; **************************************************
      ; 新int 7ch中断例程:
      ; (1) 清屏
      ; (2) 设置前景色
      ; (3) 设置背景色
      ; (4) 向上滚动一行
      ; 入口参数:
      ; (1) ah寄存器传递功能号:0清屏,1设置前景色,2设置背景色,3向上滚动一行
      ; (2) 对于2、3功能,用al传送颜色值,(al)∈
      int7ch:
      jmp set
      table dw sub1, sub2, sub3, sub4    ; 功能子程序表
      ; ****************************************
      ; 子程序sub1:
      ; 清屏
      sub1:
      push cx
      push di
      push es
      mov di, 0b800h
      mov es, di
      mov di, 0          ; es:di指向显示区字符
      mov cx, 2000       ; 一屏可显示2000个字符
      sub1s:
      mov byte ptr es:[di], ' '
      add di, 2
      loop sub1s
      pop es
      pop di
      pop cx
      ret
      ; ****************************************
      ; ****************************************
      ; 子程序sub2:
      ; 设置前景色
      sub2:
      push cx
      push di
      push es
      mov di, 0b800h
      mov es, di
      mov di, 1                         ; es:di指向显示区字符属性
      mov cx, 2000                      ; 一屏有2000个字符
      sub2s:
      and byte ptr es:[di], 11111000b   ; 前景色属性为0,1,2位
      or es:[di], al
      add di, 2
      loop sub2s
      pop es
      pop di
      pop cx
      ret
      ; ****************************************
      ; ****************************************
      ; 子程序sub3:
      ; 设置背景色
      sub3:
      push cx
      push di
      push es
      mov di, 0b800h
      mov es, di
      mov di, 1                         ; es:di指向显示区字符属性
      mov cl, 4
      shl al, cl
      mov cx, 2000                      ; 一屏有2000个字符
      sub3s:
      and byte ptr es:[di], 10001111b   ; 背景色属性为4,5,6位
      or es:[di], al
      add di, 2
      loop sub3s
      pop es
      pop di
      pop cx
      ret
      ; ****************************************
      ; ****************************************
      ; 子程序sub4:
      ; 向上滚动一行
      sub4:
      push cx
      push ds
      push si
      push es
      push di
      mov si, 0b800h
      mov ds, si
      mov es, si
      mov si, 160                       ; ds:si指向n+1行
      mov di, 0                         ; es:di指向n行
      cld                               ; 复制方向为正
      mov cx, 24                        ; 复制24行
      sub4s:
      push cx
      mov cx, 160                       ; 一行有160个字节
      rep movsb
      pop cx
      loop sub4s
      pop di
      pop es
      pop si
      pop ds
      pop cx
      ret
      ; ****************************************
      set:
      push bx
      mov bl, ah
      mov bh, 0
      add bx, bx        ; 根据功能号计算对应子程序在table表中的偏移
      call word ptr table[bx]
      pop bx
      iret
      int7chend:
      nop
      ; **************************************************
      start:
      mov ax, stack
      mov ss, ax
      mov sp, 128                              ; ss:sp指向堆栈段
      push cs
      pop ds
      mov si, offset int7ch                    ; ds:si指向源地址
      mov ax, 0
      mov es, ax
      mov di, 200H                             ; es:di指向目标地址
      mov cx, offset int7chend-offset int7ch   ; 传输长度
      cld                                      ; 传输方向为正
      rep movsb                                ; 安装中断向量
      mov word ptr es:[7ch*4], 0               ; 设置中断向量表
      mov word ptr es:[7ch*4+2], 20H           ; 20H:0为相对中断入口偏移
      mov ah, 1             ; 选择功能
      int 21h
      sub al, 30h           ; ASCII转换成数字
      mov ah, al
      cmp ah, 3
      ja exit               ; 大于3则结束
      je setscreen          ; 等于3则执行中断
      cmp ah, 0
      je setscreen          ; 等于0则执行中断
      mov bh, ah            ; 暂时保存功能号
      mov ah, 1             ; 输入颜色
      int 21h
      mov ah, bh            ; 还原功能号
      sub al, 30h           ; ASCII转换成数字
      cmp al, 7
      ja exit               ; 大于7则结束
      setscreen:
      int 7ch
      exit:
      mov ax, 4c00h
      int 21h
      code ends
      end start
      ; ****************************************
  • TA的每日心情

    2017-2-2 12:17
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    7

    主题

    215

    回帖

    959

    积分

    高级会员

    积分
    959
    nikkitang 发表于 2015-6-27 01:36:09 | 显示全部楼层
    每天都来学习,一定会进步的,加油!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|虫虫联盟 ( 备案号:蜀ICP备15018121号-1 )

    GMT+8, 2024-11-21 21:10 , Processed in 0.353353 second(s), 27 queries .

    Powered by Discuz! X3.5 Licensed

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表