汇编语言十二

assume cs:code,ss:stack

stack segment
    db 128 dup (0)
stack ends

code segment
start:
    mov ax,cs                        ;开始安装 0 号中断的中断处理程序
    mov ds,ax                        ;所谓的安装, 就是将do0子程序代码复制到一段内存区域, 这段内存区域是完全安全的
    mov si,offset do0                ;设置 ds:si 指向要复制的子程序的起始地址
    mov ax,0
    mov es,ax
    mov di,200h                     ;设置 es:di 指向该中断处理程序在内存中的起始地址
    mov cx,offset do0end-offset do0 ;计算要复制的中断处理程序有多长
    cld                             ;设置复制方向为正
    rep movsb                       ;进行代码的赋值

    mov word ptr es:[0*4],200h      ;将中断处理程序的首地址注册在中断向量表的对应表项中, 将中断例程安装在 0:200h 是由编程人员决定的
    mov word ptr es:[0*4+2],0


    mov dx,152                      ;一个检测程序
    mov ax,0
    mov cx,2
    div cx                          ;执行后, 发生除法溢出, 从而进行中断相关的工作

# 要注意的是下面的中断处理程序在本程序执行的时候并不会执行
# 只有在发生中断的时候才会执行, 并且执行的也不是这段代码
# 而是执行已经经过上面的代码复制到 0:200h 处的中断处理程序
# 所以下面的这一片只是为了复制而用的

do0:jmp short do0start               ;因为下一段代码只是数据的定义, 不是 CPU 能够识别的指令, 所以需要跳过
    db 'divide error!'
do0start:    
    mov ax,cs                        ;因为 do0 已经被安装到了 0:200h 处, 所以 cs 中的值应为 0 
    mov ds,ax
    mov si,202h                      ;因为 do0 标号处的指令占有 2 字节, 所以 ds:[202h] 指向字符串的开始位置 
    
    mov ax,0b800                    
    mov es,ax
    mov di,160*12+34*2               ;设置字符串要显示的目的地址(显示缓冲区的一段空间)
    
    mov cx,13                        ;循环 13 次
  dnext:
    mov al,[si]
    mov es:[di],al                   ;移动字符本身
    mov es:[di+1],81h                ;设置第二个字节, 即字符显示的颜色
    inc si                           ;源字符的偏移量一次增加一个字节
    add di,2                         ;目的字符的偏移量一次增加两个字节, 因为还有一个颜色属性字节
    loop dnext

    mov ah,4c                        ;返回 DOS
    int 21h
do0end:nop
code ends
end start

 

posted @ 2018-11-25 19:59  driveby  阅读(221)  评论(0编辑  收藏  举报