奥普瓯江 发表于 2019-3-27 16:32:57

检测点 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临时模拟图示这个是自己看的

Aslcwd 发表于 2019-5-8 09:16:22

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内容隔着呢?

Aslcwd 发表于 2019-5-8 09:28:40

看视频的时候我就觉得有问题
栈中内容,低到高,存着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给了标志寄存器

Aslcwd 发表于 2019-5-8 10:02:03

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

Aslcwd 发表于 2019-5-8 10:27:34

我只改动了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,此时栈内清空,模拟中断完成

Aslcwd 发表于 2019-5-8 10:29:13

楼主88行的ax要改成ah,或者数据改成1111110011111111b

奥普瓯江 发表于 2019-5-8 20:02:39

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我应该改正

Aslcwd 发表于 2019-5-10 16:54:01

奥普瓯江 发表于 2019-5-8 20:02
这里面这个call dword ptr ds:是用来模拟int 9 命令的int 9 命令的运作原理是

所以在int 9 结 ...

call的命令发出,其实是去执行真正的int 9去了,执行完毕还要iret,回到call下面那一行是吗?

奥普瓯江 发表于 2019-5-11 10:43:56

Aslcwd 发表于 2019-5-10 16:54
call的命令发出,其实是去执行真正的int 9去了,执行完毕还要iret,回到call下面那一行是吗?

嗯嗯是的,执行call下面的 in al, 61h
页: [1]
查看完整版本: 检测点 15.1