int指令也是一种内中断指令,int指令的格式为int n,n是中断类型码。也就是说,使用int指令可以调用任意的中断例程,例如我们可以显示的调用0号中断例程,还记得在汇编学习笔记(10)中我们自己定义了除法溢出的例程么,我们在这里直接调用看看
1 assume cs:codesg 2 3 codesg segment 4 5 start: 6 mov ax,0b800h 7 mov es,ax 8 mov byte ptr es:[11*160+40*2],'h' 9 int 0 10 11 codesg ends 12 13 end start
成了,perfect!
既然可以随时随地的调用中断例程,那么就可以借助中断例程来完成一些系统必须的子程序,下面是书上的例子,当次搬运工
1 ;编写7ch号中断例程,计算word型数据的平方 2 assume cs:codesg 3 4 codesg segment 5 6 start: 7 ;ds:si指向sqr 8 mov ax,cs 9 mov ds,ax 10 mov si,offset sqr 11 ;es:di指向0000:01e0 12 mov ax,0000 13 mov es,ax 14 mov di,01e0h 15 ;安装 16 mov cx,offset sqrend-offset sqr 17 cld 18 rep movsb 19 ;设置中断向量表 20 mov ax,0000 21 mov es,ax 22 mov word ptr es:[7ch*4],01e0h 23 mov word ptr es:[7ch*4+2],0 24 mov ax,8888 25 int 7ch 26 27 mov ax,4c00h 28 int 21h 29 sqr: 30 mul ax 31 iret 32 sqrend: 33 nop 34 35 codesg ends 36 37 end start
1 ;编写7ch号中断例程,将字符串全部转换为大写 2 assume cs:codesg,ds:data 3 data segment 4 db 'h',0 5 data ends 6 codesg segment 7 8 start: 9 ;ds:si指向sqr 10 mov ax,cs 11 mov ds,ax 12 mov si,offset upper 13 ;es:di指向0000:01e0 14 mov ax,0000 15 mov es,ax 16 mov di,01e0h 17 ;安装 18 mov cx,offset upperend-offset upper 19 cld 20 rep movsb 21 ;设置中断向量表 22 mov ax,0000 23 mov es,ax 24 mov word ptr es:[7ch*4],01e0h 25 mov word ptr es:[7ch*4+2],0 26 mov ax,data 27 mov ds,ax 28 mov si,0 29 mov cl,11 30 ;显示原始字符串 31 call display 32 ;调用中断程序 33 int 7ch 34 ;大写 35 call upper 36 mov cl,12 37 ;显示改写后的字符串 38 call display 39 40 mov ax,4c00h 41 int 21h 42 upper: 43 push cx 44 push si 45 change: 46 mov cl,[si] 47 mov ch,0 48 jcxz s0 49 and byte ptr [si],11011111b 50 inc si 51 jmp short change 52 s0: 53 pop si 54 pop cx 55 iret 56 upperend: 57 nop 58 59 display: 60 push ax 61 push es 62 push di 63 push si 64 push cx 65 mov ax,0b800h 66 mov es,ax 67 mov ax,160 68 mul cl 69 add ax,80 70 mov di,ax 71 mov ch,0 72 s1: 73 mov cl,ds:[si] 74 jcxz ok 75 mov byte ptr es:[di],cl 76 add di,2 77 inc si 78 jmp short s1 79 ok: 80 pop cx 81 pop si 82 pop di 83 pop es 84 pop ax 85 ret 86 codesg ends 87 88 end start
中断例程实现loop指令需要完成以下功能:
1.(cx)=(cx)-1
2.如果(cx)!=0,循环执行,否则向下继续执行
为了完成上述的两种功能,显然中断例程必须获取cs和ip的值。因调用中断例程是现将cs、ip入栈,所以只需将ip的值减去循环体的长度就可以了
1 assume cs:code 2 3 code segment 4 5 start: 6 mov ax,cs 7 mov ds,ax 8 mov si,offset looper 9 mov ax,01e0h 10 mov es,ax 11 mov di,0 12 mov cx,offset l-offset looper 13 cld 14 rep movsb 15 mov ax,0 16 mov es,ax 17 mov word ptr es:[7ch*4],01e0h 18 mov word ptr es:[7ch*4+2],0 19 mov ax,0b800h 20 mov es,ax 21 mov di,12*160 22 mov bx,offset s-offset send 23 mov cx,80 24 s: 25 mov byte ptr es:[di],'!' 26 add di,2 27 int 7ch 28 send: 29 nop 30 mov ax,4c00h 31 int 21h 32 33 looper: 34 push bp 35 mov bp,sp 36 dec cx 37 jcxz loopend 38 add [bp+2],bx 39 loopend: 40 pop bp 41 iret 42 l: 43 nop 44 code ends 45 46 end start
BIOS提供了很多中断例程以供调用,下面举个显示字符串的例子,int 10h例程中的9号子程序
1 assume cs:code 2 3 code segment 4 5 start: 6 mov ah,2 7 mov bh,0 8 mov dh,5 9 mov dl,12 10 int 10h 11 12 mov ah,9 13 mov al,'a' 14 mov bl,11001010b 15 mov bh,0 16 mov cx,3 17 int 10h 18 mov ax,4c00h 19 int 21h 20 code ends 21 22 end start
端口的读写只有两种指令和寄存器可以使用
CMOS芯片包含两个端口70h和71h,70h是地址端口,71h是数据端口,从CMOS RAM中读取2号单元内容程序如下
1 assume cs:code 2 3 code segment 4 5 start: 6 mov al,2 7 out 70h,al ;表示要读取2号单元 8 in al,71h;读取2号单元内容 9 10 mov ax,4c00h 11 int 21h 12 code ends 13 14 end start
写入的是这样
1 assume cs:code 2 3 code segment 4 5 start: 6 mov al,2 7 out 70h,al ;表示要写入2号单元 8 mov al,0 9 out 71h,al;写入0 10 11 mov ax,4c00h 12 int 21h 13 code ends 14 15 end start
shl是逻辑左移指令,shr是逻辑右移指令。左移的最低位和右移的最高位都用0补充,并将移出的最后一位写入CF中,不论左移还是右移,都是从最低位开始的。
mov al,10010000
shl al,1
shr al,1
左移后(al)=00100000 CF=1,右移后(al)=00010000 CF=0.左移一位相当于x=x*2,右移一位相当于x=x/2.
1 assume cs:code,ds:data 2 3 data segment 4 db 'yy/mm/dd hh:mm:ss','$' 5 index db 9,8,7,4,2,0 6 data ends 7 8 code segment 9 10 start: 11 mov ax,data 12 mov ds,ax 13 mov si,0 14 mov di,0 15 mov cx,6 16 s: 17 push cx 18 ;获取需要读取的端口地址 19 mov al,index[si] 20 out 70h,al 21 in al,71h 22 23 mov ah,al 24 mov cl,4 25 ;取得十位 26 shr ah,cl 27 ;个位 28 and al,00001111b 29 ;转为字符 30 add ah,30h 31 add al,30h 32 33 mov ds:[di],ah 34 mov ds:[di+1],al 35 36 inc si 37 add di,3 38 39 pop cx 40 loop s 41 ;光标显示位置 42 mov ah,2 43 mov bh,0 44 mov dh,10 45 mov dl,40 46 int 10h 47 ;显示ds:dx指向的字符串 48 mov ax,data 49 mov ds,ax 50 mov dx,0 51 mov ah,9 52 int 21h 53 54 55 mov ax,4c00h 56 int 21h 57 code ends 58 59 end start