龙龙 发表于 2015-6-22 03:15:57

汇编作业 实验16

  这个实验比较有趣,光看书写出来的程序总是运行不正确
  不断调试后才发现原来是在偏移地址的计算中出现了错误
  以下情况是在代码中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时,(table)的实际值,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:, ' '
  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:, 11111000b   ; 前景色属性为0,1,2位
  or es:, 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:, 10001111b   ; 背景色属性为4,5,6位
  or es:, 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
  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:, 0               ; 设置中断向量表
  mov word ptr es:, 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
  ; ****************************************

nikkitang 发表于 2015-6-27 01:36:09

每天都来学习,一定会进步的,加油!
页: [1]
查看完整版本: 汇编作业 实验16