13.1 int 指令
int指令:其实就是转到对应的中断指令
int n
过程:
(1)取中断码
(2)标志寄存器入栈,IF=0,TF=0
(3)CS,IP入栈
(4)(IP)=(n*4),(CS)=(n*4+2)
assume cs:code
code segment
start:mov ax,0b800h
mov es,ax
mov byte ptr es:[12*160+40*2],'!'
int 0
code ends
end start
winxp执行
13.2 编写供应用程序调用的中断例程(中断程序)
问题一求平方:
;求ax平方 高16位放到DX,低16为放到AX中
assume cs:code
code segment
start: mov ax,cs
mov ds,ax
mov si,offset sqr ;ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h ;es:di指向目的地址
mov cx,offset sqrend -offset sqr ;设置cx
cld ;正向传输
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
mov ax,1234
int 7ch
mov ax,4c00h
int 21h
sqr: mul ax
iret
sqrend:nop
code ends
end start
问题二:大写转小写
(显示到屏幕是我自己添的)
assume cs:code
code segment
start: ;将下边capital大小写转换代码看作数据转移到0000:0200的地方
mov ax,cs
mov ds,ax ;因为下边想用movsb那个可以将ds:si中的内容一下子放到es:di中的厉害指令
mov si,offset capital ;因为要复制的指令(源)(机器码)在cs中,所以要将cs给ds,si就是capital对应的偏移地址,这里用offset就好啦
;一定一定要注意的是,ds:si--->es:di因为这个错误折磨了我一上午。我把si和di写反了。
mov ax,0 ;这里就是设置目的地址了,将es:di设置到0000:0200就好
mov es,ax
mov di,200h
mov cx,offset capitalend-offset capital ;这个cx嘛是要复制数据的长度用偏移地址相减就欧克
cld ;不能让他倒着复制要不然就麻烦了,这条指令是设置正着复制的
rep movsb ;一把梭哈,一步到位,这条指令就是那个特别厉害的指令,可以一口气将cx
;长度的机器码(就是内存中的内容)复制到es:di中,,记住是ds:si--->es:di
mov ax,0 ;这里是设置7ch中断的,将中断例程和地址对应起来
;专业点好像是叫将7ch中断例程的段地址和偏移地址写到中断向量表中
mov es,ax
mov word ptr es:[7Ch*4],200h
mov word ptr es:[7Ch*4+2],0
int 7CH ;调用7ch中断例程
mov ax,4c00h
INT 21H
capital: push cx ;将用到的寄存器保护起来和下边的pop对应
push si
push ax
push ds
push cs
push es
push bp
jmp short change ;这里是数据,因为不是指令所以不能让他执行,要跳过
db 'llllll'
db 'oooooooooooooo',0
change: mov ax,0b800h ;设置一下用到的寄存器,不可以在change里设置,
;因为跳转的时候会重新设置,这样就会一直读取一个东西或者写入到一个地方
mov es,ax
mov bp,160*12+2*40 ;我想让他写到这里,将转换后的数据
mov ax,0
mov si,209h ;这个是刚刚数据存放的地址,可以从200开始数,反正我是数的
change2: mov cl,cs:[si] ;将读入的数据放到cl中,因为要一个一个的转换,一个字母是8为,一个字节,对应半个16位寄存器
mov ch,0 ;将ch=0,这样cl=0一定就会使cx=0,下边的jcxz才好使
jcxz ok ;如果读到0了就跳转到不向下执行了直接到ok
and byte ptr cs:[si],11011111b ;这个就是让小写变成大写的指令,当然不止一个,但是这里用这个吧,因为书上用的这个
mov al,cs:[si] ;转换后我想看看有没有成功,久让他在屏幕上显示了
mov es:[bp],al
add bp,2 ;因为显示到屏幕是偶数是内容,奇数是属性,我们不用设置属性直接跳过加2
inc si ;读取下一个字母
jmp short change2 ;跳转到change2
ok:
pop bp
pop es
pop ax
mov cs,ax
pop ds
pop ax
pop si
pop cx
iret ;和call对应ret类似,int要对应iret好一点
capitalend:nop
code ends
end start
结果
13.3对·int、iret和栈的深入理解
问题:用7ch中断完成loop指令功能
在屏幕显示80个“!”
assume cs:code
code segment
start: ;安装7ch
mov ax, cs
mov ds,ax
mov si,offset lp
mov ax,0
mov es,ax
mov ax,200h
mov di,ax
mov cx,offset lpret-offset lp+2 ;刚开始不行怀疑是没有安装全,+1也不行,+2才可以
cld
rep movsb
;设置中断向量表
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0h
;显示!到屏幕
mov ax,0b800h
mov es,ax
mov di,160*12
;用bx保存偏移地址
mov bx,offset s-offset se
mov cx,80
;
s: mov byte ptr es:[di],'!'
add di,2
int 7ch
se: nop
mov ax,4c00h
int 21h
;把用到的寄存器保护起来
;这个时候栈的情况是这样的
;bp
;se的ip ss*16+bp+2
;se的cs
;bp是用来保存栈顶的sp的
lp: push bp
mov bp,sp ;将sp给到bp
dec cx
jcxz lpret ;cx!=0就跳转,也就是不更改cs:ip
add [bp+2],bx
lpret:pop bp
iret ;出栈,如果更改了,就出栈更改后的,没有更改就是之前的,就不会循环了
code ends
end start
结果:
监测点13.1
将data段(以0结尾)的数据,显示到屏幕上
assume cs:code
data segment
db 'conversation',0
data ends
code segment
start:
;安装7ch
mov ax, cs
mov ds,ax
mov si,offset lp
mov ax,0
mov es,ax
mov ax,200h
mov di,ax
mov cx,offset lpret-offset lp+2 ;刚开始不行怀疑是没有安装全,+1也不行,+2才可以
cld
rep movsb
;设置中断向量表
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0h
mov ax,data
mov ds,ax
mov si,0
mov ax,0b800h
mov es,ax
mov di,12*160
s: cmp byte ptr [si],0
je ok
mov al,[si]
mov es:[di],al
inc si
add di,2
mov bx,offset s-offset ok
int 7ch
ok: mov ax,4c00h
int 21h
;把用到的寄存器保护起来
;这个时候栈的情况是这样的
;bp
;se的ip ss*16+bp+2
;se的cs
;bp是用来保存栈顶的sp的
lp: push bp
mov bp,sp ;将sp给到bp
add [bp+2],bx
lpret:pop bp
iret ;出栈,如果更改了,就出栈更改后的,没有更改就是之前的,就不会循环了
code ends
end start
结果: