狂潮丶 发表于 2013-8-5 22:18:04

Assembly language 实验16

实验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)∈{0, 1, 2, 4, 5, 6, 7}
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
; ****************************************




**** Hidden Message *****

魔灬鹰 发表于 2013-8-19 13:08:49

{:2_31:}一楼我的

czl 发表于 2013-11-10 22:10:15

:handshake3Q..........

E=MC2 发表于 2013-11-10 22:53:17

看看最后写什么了。。

dugwei 发表于 2014-4-2 19:05:11

直接定指标 王爽的书讲得不完善,坛主也不具体运行一下,唉!!!

九叶子青年 发表于 2014-4-2 20:17:07

楼主真给力啊

C瓶 发表于 2014-4-2 20:47:06

看看最后写什么了。。

qq353584009 发表于 2014-4-7 22:21:56

3Q3Q..........

huainian 发表于 2014-6-11 07:31:32

谢谢分享!!!!!!!!!!!!!1{:2_35:}

HTT_音乐 发表于 2014-7-2 15:19:14

学习了,我调试了一上午都没弄好

河蟹代码 发表于 2014-7-3 12:07:03

看看隐藏的是什么

河蟹代码 发表于 2014-7-3 12:07:42

河蟹代码 发表于 2014-7-3 12:07 static/image/common/back.gif
看看隐藏的是什么

靠,啥都木有,蒙我呢。。。。。

qianmin 发表于 2014-7-3 12:58:22

这时候一般我们应该回复一下,以表示礼貌

jianchixuexi 发表于 2014-7-9 22:10:41

看看,学习学习

nirvana436 发表于 2016-2-4 12:45:26

还是有一些不清楚,再研究下

缌唸 发表于 2016-3-24 21:35:56

楼主解释很棒

kyowjw01 发表于 2017-6-13 13:35:11

{:10_261:}路过愁一愁。

RenZhongkai 发表于 2019-8-7 18:04:28

感谢

SetsunaFH 发表于 2020-5-9 14:04:03

看看

jie杰 发表于 2022-6-27 12:32:10

1
页: [1]
查看完整版本: Assembly language 实验16