汇编学习--第十七天
检测点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