编写中断程序 ,使得在每执行一行命令,都会打印出相对应的偏移地址
测试代码:
assume cs:code
code segment
start:
编写代码区
mov bx,0
mov ax,30
sub cx,1
mov ax,4c00h
int 21h
如果要想使得没执行一行代码,都打印偏移地址,那么我们首先会考虑用到单步中断。
(1)CPU执行 int 指令过程:
a.取中断类型
b.标志寄存器入栈,IF TF置0
c.CS IP入栈
d.(IP)=(N* 4),(CS) = (N* 4+2)
(2)当TF = 1时,CPU在执行完一条指令后将引发单步中断,转去执行中断处理程序。
所以,我们需要在单步中断程序中将标志寄存器中的TF位置1,这样当第一次手动调用int 1之后,在每次命令执行之前,标志寄存器内的TF都为1,这样每次都能执行单步中断,除非遇到 int 调用别的中断,这样会将TF置0.
(3)我们要先搞清楚,CPU在执行指令的时候IP地址是如何变化的,经过之前的学习,我们了解到: 当当前指令放入指令缓存器内还没有执行的时候,此时的IP已经自动增加到下一个指令的IP处。所以我们调用 int 1 时,不会打印int 1的偏移地址,是从它之后的指令开始打印。
assume cs:code
code segment
start: mov ax,cs
mov ds,ax
mov si,offset int1
mov di,200h
mov ax,0
mov es,ax
mov cx,offset int1end-offset int1
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[4*1h],200h
mov word ptr es:[4*1h+2],0
mov di,160*12
int 1
mov bx,0
mov ax,30
sub cx,1
mov ax,4c00h
int 21h
int1: jmp short int1s
db"0123456789ABCDEF"
int1s:
push bp
mov bp,sp
push ax
push bx
push cx
mov ax,[bp+6] //此处是存放标志寄存器的位置
or ah,00000001b //将TF位置1,实现单步中断
mov [bp+6],ax
mov ax,[bp+2] //取出ip地址到ax,为了后面注释好理解 例如ip = 1234h
call show
pop cx
pop bx
pop ax
pop bp
iret
show: push bx
push es
push dx
push cx
mov bl,ah //取出12h赋给bl,然后右移,取到数值1
mov cl,4
shr bl,cl
and ah,00001111b //将12h进行与运算,取到数值2
mov bh,0
mov bl,cs:[bx+202h] //202h对应的正好是中断程序给出的字符串0-F,将‘1’字符取出
mov dx,0b800h
mov es,dx
mov es:[di+40*2],bl //打印
mov bl,ah //将02h赋给bl,之后用bx在1-F中查找对应的字符‘2’
mov bh,0
mov ah,cs:[bx+202h]
mov es:[di+41*2],ah
mov ah,al //取出34h赋给ah,然后右移,取到数值3
shr ah,cl
and al,00001111b //将12h进行与运算,取到数值4
mov bl,ah //之后的思路同上
mov bh,0
mov ah,cs:[bx+202h] //打印3
mov es:[di+42*2],ah
mov bl,al
mov bh,0
mov al,cs:[bx+202h] //打印4
mov es:[di+43*2],al
add di,160
pop cx
pop dx
pop es
pop bx
ret
int1end: nop
code ends
end start