汇编学习--第十七天

检测点15.1

(1)

pushf

call dword ptr ds:[0]

 

(2)

设置int 9中断例程的地址的指令有两个部分:

;设置新int9中断例程入口地址
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs

 

;恢复原来int9中断例程入口地址
mov ax,0
mov es,ax
push ds:[0]
pop es:[9*4]
push ds:[2]
pop es:[9*4+2]

 

在执行指令期间可能发生键盘中断,引发错误的地址执行,也就是IF寄存器可能为1,所以只要我们在执行这两段指令之间,令IF=0,即可保证程序正确。

cli
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs
sti

 

cli
mov ax,0
mov es,ax
push ds:[0]
pop es:[9*4]
push ds:[2]
pop es:[9*4+2]
sti

 

15.5 安装新的int 9中断例程

在DOS下,按F1键后改变当前屏幕的显示颜色

assume cs:code
stack segment
    db 128 dup (0)
stack ends
code segment
start:
    ;栈段地址
    mov ax,stack
    mov ss,ax
    mov sp,128
    
    ;将新中断例程保存到0:204h
    push cs
    pop ds
    mov ax,0
    mov es,ax
    
    mov di,204h
    mov si,offset int9
    mov cx,offset int9end-offset int9
    cld
    rep movsb
    
    ;原int 9中断向量表中的入口地址保存到0:200h~203h
    push es:[9*4]
    pop es:[200h]
    push es:[9*4+2]
    pop es:[202h]
    
    ;设置新int9中断例程入口地址
    cli
    mov word ptr es:[9*4],204h
    mov word ptr es:[9*4+2],0
    sti
    
    mov ax,4c00h
    int 21h
    
    ;新中断例程
int9:
    push ax
    push bx
    push es
    push cx
    ;从60端口读出键盘的输入
    in al,60h
    
    pushf
    call dword ptr cs:[200h]

    cmp al,3bh;判断是否按下F1
    jne int9ret
    
    mov ax,0b800h
    mov es,ax
    mov bx,1
    mov cx,2000;一屏幕4000字节
s:
    inc byte ptr es:[bx]
    add bx,2
    loop s
    
int9ret:
    pop cx
    pop es
    pop bx
    pop ax
    iret
int9end:nop
    
code ends
end start

 

实验15 安装新的int 9中断例程

assume cs:code
stack segment
    db 128 dup (0)
stack ends
code segment
start:
    mov ax,stack
    mov ss,ax
    mov sp,128

    ;将中断例程写到0:204h
    push cs
    pop ds
    
    mov ax,0
    mov es,ax
    
    mov cx,offset int9end-offset int9
    mov si,offset int9
    mov di,204h
    cld
    rep movsb
    
    ;将原int 9中断例程入口地址保存到0:200h
    push es:[9*4]
    pop es:[200h]
    push es:[9*4+2]
    pop es:[202h]
    
    ;将新的中断例程入口地址写入中断向量表
    cli
    mov word ptr es:[9*4],204h
    mov word ptr es:[9*4+2],0
    sti
    
    mov ax,4c00h
    int 21h
    
int9:
    push ax
    push bx
    push cx
    push es
    ;从端口读取键盘数据
    in al,60h
    
    ;调用原来的int 9中断例程,此时CS=0
    pushf
    call dword ptr cs:[200h]
    
    ;比较是否收到A键值
    cmp al,9eh
    jne int9ret
    
    ;显示一屏幕A
    mov ax,0b800h
    mov es,ax
    mov bx,0
    mov cx,2000
s:
    mov byte ptr es:[bx],'A'
    add bx,2
    loop s
int9ret:
    pop es
    pop cx
    pop bx
    pop ax
    iret

int9end:nop
code ends
end start

 

第16章 直接定址表

16.1 描述了单元长度的标号

assume cs:code
code segment
    a:    db 1,2,3,4,5,6,7,8
    b:    dw,0
start:
    mov si,offset a
    mov bx,offset b
    mov cx,8
s:
    mov al,cs:[si]
    mov ah,0
    add cs:[bx],ax
    inc si
    loop s
    
    mov ax,4c00h
    int 21h
code ends
end start

在上面的代码中,a,b仅仅代表了内存单元的地址

 

assume cs:code
code segment
    a    db 1,2,3,4,5,6,7,8
    b    dw 0
start:
    mov si,0
    mov cx,8
s:
    mov al,cs:[si]
    mov ah,0
    add b,ax
    inc si
    loop s
    
    mov ax,4c00h
    int 21h
code ends
end start

在上面代码中,a,b是同时描述了内存地址和单元长度,例如:a表示,地址code:0开始,以后的内存单元都是字节单元。

 

检测点 16.1

assume cs:code
code segment
    a    dw 1,2,3,4,5,6,7,8
    b    dd 0
start:
    mov si,0
    mov cx,8
s:
    mov ax,a[si]
    add word ptr b[0],ax
    adc word ptr b[2],0
    add si,2
    loop s
    
    mov ax,4c00h
    int 21h
code ends
end start

 

 

16.2 在其他段中使用数据标号

后面加有“:”的地址标号,只能在代码段中使用。

要在代码段中直接使用数据标号访问数据,则需要用伪指令assume将标号所在段和一个寄存器联系起来。

 

assume cs:code,ds:data
data segment
    a db 1,2,3,4,5,6,7,8
    b dw 0
data ends
code segment
start:
    mov ax,data
    mov ds,ax
    
    mov si,0
    mov cx,8
s:
    mov al,a[si]
    mov ah,0
    add b,ax
    inc si
    loop s
    
    mov ax,4c00h
    int 21h
code ends
end start

 

data segment
    a db 1,2,3,4,5,6,7,8
    b dw 0
    c dw a,b
data ends

相当于:

data segment
    a db 1,2,3,4,5,6,7,8
    b dw 0
    c dw offset a,offset b
data ends

 

data segment
    a db 1,2,3,4,5,6,7,8
    b dw 0
    c dd a,b
data ends

相当于

data segment
    a db 1,2,3,4,5,6,7,8
    b dw 0
    c dd offset a,seg a,offset b,seg b
data ends

seg 为获得某一标号的段地址

 

检测点 16.2

mov ax,data

mov ds,ax

 

16.3 直接定址表

编写子程序,以十六进制形式在屏幕中间显示给定的字节数据

assume cs:code,ds:data
data segment
    table db '0123456789ABCDEF'
data ends
code segment
start:
    mov ax,data
    mov ds,ax
    mov al,0BCH
    ;高8位和低8位分离
    mov ah,al
    mov cl,4
    shr ah,cl
    and al,00001111b
    
    mov bx,0b800h
    mov es,bx
    mov di,12*160+40*2
    ;在table中找到对应位置,显示
    mov bl,ah
    mov bh,0
    mov ah,table[bx]
    mov es:[di],ah
    
    mov bl,al
    mov bh,0
    mov al,table[bx]
    mov es:[di+2],al
    
    mov ax,4c00h
    int 21h
code ends
end start

 

 

显示sin(x)的值

assume cs:code
code segment
start:
    mov al,90;度数
    call showsin
    
    mov ax,4c00h
    int 21h

showsin: 
    jmp short show
    table dw ag0,ag30,ag60,ag90,ag120,ag150,ag180
    ag0   db '0',0
    ag30  db '0.5',0
    ag60  db '0.866',0
    ag90  db '1',0
    ag120 db '0.866',0
    ag150 db '0.5',0
    ag180 db '0',0

show:
    push bx
    push es
    push di

    mov bx,0b800h
    mov es,bx
    mov di,160*12+40*2
    
    mov ah,0       
    mov bl,30      
    div bl
    mov bl,al      
    mov bh,0
    add bx,bx     
    mov bx,cs:table[bx]      

shows:
    mov ah,cs:[bx]     
      cmp ah,0          
    je showret
      mov es:[di],ah     
    inc bx            
    add di,2
    jmp short shows

showret:
    pop di
    pop es
    pop bx
    ret
code ends
end start

 

posted @ 2019-07-26 23:59  Hk_Mayfly  阅读(257)  评论(0编辑  收藏  举报