检测点 15.1
本帖最后由 奥普瓯江 于 2019-3-27 16:43 编辑(1)仔细分析一下上面的int 9 中断例程, 看看是否可以精简一下?
其实在我们的int 9 中断例程中, 模拟int 指令调用原int 9 中断例程的程序段是可以精简的, 因为在进入中断例程后, IF 和 TF都已经置0,没有必要在进行设置了。
对于程序段:
pushf
pushf
pop ax
andah, 11111100b
push ax
popf
call dword ptr ds:
可以精简为:
pushf ;因为下面的返回中call模拟int 9h 程序返回时需要 寄存器数据,所以这里需要向栈中输入一个cf寄存器数据供下面call中的iret返回使用
call dword ptr ds: ;这个是必须有的所以他不能动模拟int 9 程序
原程序如下:
assume cs:code, ds:data_1, ss:stack
data_1 segment
dw 0,0
data_1 ends
stack segment
db 128 dup (0)
stack ends
code segment
start:
mov ax, data_1 ;数据段
mov ds, ax
mov si, 0
mov ax, stack ;栈定义,这里定义不定义栈其实无所谓,因为编译器会自动定义栈位ffff
mov ss, ax
mov sp, 128
mov ax, 0
mov es, ax
;把int 9h中断限量表中的地址传给数据段0、1和2、3, 这样中断限量表中的int 9h 中断就不会消失了,他的地址一致会储存在数据段中随时让我们可以调用
push es: ;低位为偏移地址
popds: ;ds低位为偏移地址储存
push es: ;高位为段地址
pop ds: ;ds高位为短地址储存
mov word ptr es:, offset int9 ;偏移地址
mov word ptr es:, cs ;短地址每个地址占两个字节一共4个字节
mov ax, 0b800h
mov es, ax
mov ah, 'a'
s:
mov byte ptr es:, ah
inc ah
call jump_1
cmp ah, 'z'
jna s
;把中断向量表中的地址恢复成初始地址
mov ax, 0
mov es, ax
push word ptr ds:
pop word ptr es:
push word ptr ds:
pop word ptr es:
mov ax, 4c00h
int 21h
jump_1:
push ax
push dx
mov ax, 0
mov dx, 1000h
jump_2:
sub ax, 1
sbb dx, 0
cmp ax, 0 ;内循环
jne jump_2
cmp dx, 0 ;外循环
jne jump_2
pop dx
pop ax
ret
int9:
push ax
push es
push ds
pushf
pushf
pop ax
and ax, 11111100b
push ax
popf
call dword ptr ds:
in al, 60h
cmp al, 1
jne good
inc byte ptr es:
good:
pop ds
pop es
pop ax
iret
code ends
end start
int 9临时模拟图示这个是自己看的
int9段我有疑问
push了ax、es、ds,再pushf两次,pop,push、popf,call dw
那么栈中内容,低到高,存着ip、cs、pushf、ds、es、ax
然后跳转到good,就能直接pop
ds、es、ax?
怎么看都是错的吧!
还有ip、cs、pushf内容隔着呢? 看视频的时候我就觉得有问题
栈中内容,低到高,存着ip、cs、pushf、ds、es、ax
接下来由good,完成了6次pop,但是顺序不对
good:
pop ds ;看顺序应该是ip
pop es ;cs
pop ax ;pushf
iret ;完成了ds给ip,es给cs,ax给了标志寄存器 assume cs:code, ds:data_1, ss:stack
data_1 segment
dw 0,0
data_1 ends
stack segment
db 128 dup (0)
stack ends
code segment
start:
mov ax, data_1 ;数据段
mov ds, ax
mov si, 0
mov ax, stack ;栈定义,这里定义不定义栈其实无所谓,因为编译器会自动定义栈位ffff
mov ss, ax
mov sp, 128
mov ax, 0
mov es, ax
;把int 9h中断限量表中的地址传给数据段0、1和2、3, 这样中断限量表中的int 9h 中断就不会消失了,他的地址一致会储存在数据段中随时让我们可以调用
push es: ;低位为偏移地址
popds: ;ds低位为偏移地址储存
push es: ;高位为段地址
popds: ;ds高位为短地址储存
mov word ptr es:, offset int9 ;偏移地址
mov word ptr es:, cs ;短地址每个地址占两个字节一共4个字节
mov ax, 0b800h
mov es, ax
mov ah, 'a'
s:
mov byte ptr es:, ah
inc ah
call jump_1
cmp ah, 'z'
jna s
;把中断向量表中的地址恢复成初始地址
mov ax, 0
mov es, ax
push word ptr ds:
pop word ptr es:
push word ptr ds:
pop word ptr es:
mov ax, 4c00h
int 21h
jump_1:
push ax
push dx
mov ax, 0
mov dx, 1000h
jump_2:
sub ax, 1
sbb dx, 0
cmp ax, 0 ;内循环
jne jump_2
cmp dx, 0 ;外循环
jne jump_2
pop dx
pop ax
ret
int9:
pushf
push ax
pushf
pop ax
and ax, 11111100b
push ax
popf
pop ax
call dword ptr ds:
push ax
push es
push ds
in al, 60h
cmp al, 1
jne good
inc byte ptr es:
good:
pop ds
pop es
pop ax
iret
code ends
end start 我只改动了int9的内容
int9:
pushf ;标志寄存器入栈,栈内数据低到高:flag
push ax ;ax入栈保护,栈内数据低到高:ax,flag
pushf ;标志寄存器再次入栈,栈内数据低到高:flag,ax,flag
pop ax ;标志寄存器,弹出给ax,栈内数据低到高:ax,flag
and ah, 11111100b ;这里是楼主的88行,代码写错,TF和IF清零,应该使用高位ah,栈内数据低到高:ax,flag
push ax ;TF、IF置零后的寄存器数据在ax中,入栈,栈内数据低到高:ax(flag),ax,flag
popf ;新的flag置零完毕,栈内数据低到高:ax,flag
pop ax ;还原ax的值,栈内数据低到高:flag
call dword ptr ds: ;双字call命令,CS入栈,IP入栈,栈内数据低到高:ip,cs,flag
;此时栈内有flag标志寄存器,cs代码段地址,ip偏移地址,相当于完成了int 9的前3步,call命令完成了int 9的第四步
;从此刻开始,模拟调用了int 9的中断命令,栈内数据低到高:ip,cs,flag
push ax ;入栈各个寄存器
push es
push ds ;入栈三个,栈内数据低到高:ds,es,ax,ip,cs,flag
in al, 60h ;寄存器保存好,开始运行键盘的外部中断,此步为读取端口,栈内数据低到高:ds,es,ax,ip,cs,flag
cmp al, 1 ;比较esc的通码,栈内数据低到高:ds,es,ax,ip,cs,flag
jne good ;不是则跳转good,是则向下执行变色
inc byte ptr es: ;变色
good:
pop ds ;弹出ds,栈内数据低到高:es,ax,ip,cs,flag
pop es ;弹出es,栈内数据低到高:ax,ip,cs,flag
pop ax ;弹出ax,栈内数据低到高:ip,cs,flag
iret ;恢复ip、恢复cs、恢复flag,此时栈内清空,模拟中断完成 楼主88行的ax要改成ah,或者数据改成1111110011111111b Aslcwd 发表于 2019-5-8 09:16
int9段我有疑问
push了ax、es、ds,再pushf两次,pop,push、popf,call dw
那么栈中内容,低到高,存着i ...
这里面这个call dword ptr ds:是用来模拟int 9 命令的int 9 命令的运作原理是
所以在int 9 结束的时候已经把 你所说的 ip cs pushf都已经释放了所以不存在隔着的情况
在这里你指出的那个and ax,11111100b那个是我错了这个应该是ah我应该改正 奥普瓯江 发表于 2019-5-8 20:02
这里面这个call dword ptr ds:是用来模拟int 9 命令的int 9 命令的运作原理是
所以在int 9 结 ...
call的命令发出,其实是去执行真正的int 9去了,执行完毕还要iret,回到call下面那一行是吗? Aslcwd 发表于 2019-5-10 16:54
call的命令发出,其实是去执行真正的int 9去了,执行完毕还要iret,回到call下面那一行是吗?
嗯嗯是的,执行call下面的 in al, 61h
页:
[1]