鱼C论坛

 找回密码
 立即注册
查看: 2958|回复: 8

[汇编作业] 检测点 15.1

[复制链接]
发表于 2019-3-27 16:32:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 奥普瓯江 于 2019-3-27 16:43 编辑

(1)仔细分析一下上面的int 9 中断例程, 看看是否可以精简一下?
                其实在我们的int 9 中断例程中, 模拟int 指令调用原int 9 中断例程的程序段是可以精简的, 因为在进入中断例程后, IF 和 TF都已经置0,没有必要在进行设置了。
对于程序段:
                pushf
                pushf
                pop ax
                and  ah, 11111100b
                push ax
                popf
                call dword ptr ds:[0]

可以精简为:
                pushf                                                ;因为下面的返回中call模拟int 9h 程序返回时需要 寄存器数据,所以这里需要向栈中输入一个cf寄存器数据供下面call中的iret返回使用
                call dword ptr ds:[0]                ;这个是必须有的所以他不能动模拟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:[9 * 4]                ;低位为偏移地址
                pop  ds:[0]                        ;ds低位为偏移地址储存
                
                push es:[9 * 4 + 2] ;高位为段地址
                pop         ds:[2]                        ;ds高位为短地址储存
                
                mov word ptr es:[9 * 4], offset int9       ;偏移地址
                mov word ptr es:[9 * 4 + 2], cs                          ;短地址每个地址占两个字节一共4个字节
                
                
                
                
                mov ax, 0b800h
                mov es, ax
                mov ah, 'a'
s:
                mov byte ptr es:[160 * 12 + 40 * 2], ah
                inc ah
                call jump_1
                cmp ah, 'z'
                jna s
                
                ;把中断向量表中的地址恢复成初始地址
                mov ax, 0
                mov es, ax
                
                push word ptr ds:[0]
                pop word ptr es:[9 * 4]
                
                push word ptr ds:[2]
                pop word ptr es:[9 * 4 + 2]
                
                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:[0]
                
                
                in al, 60h

                cmp al, 1
                jne good
                
                inc byte ptr es:[160 * 12 + 40 * 2 + 1]
                
good:
                pop ds
                pop es
                pop ax
                iret
                
code ends
end start

int 9临时模拟图示这个是自己看的
绘图1.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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内容隔着呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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给了标志寄存器
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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:[9 * 4]                ;低位为偏移地址
                pop  ds:[0]                        ;ds低位为偏移地址储存
               
                push es:[9 * 4 + 2] ;高位为段地址
                pop  ds:[2]                        ;ds高位为短地址储存
               
                mov word ptr es:[9 * 4], offset int9       ;偏移地址
                mov word ptr es:[9 * 4 + 2], cs                          ;短地址每个地址占两个字节一共4个字节
               
               
               
               
                mov ax, 0b800h
                mov es, ax
                mov ah, 'a'
s:
                mov byte ptr es:[160 * 12 + 40 * 2], ah
                inc ah
                call jump_1
                cmp ah, 'z'
                jna s
               
                ;把中断向量表中的地址恢复成初始地址
                mov ax, 0
                mov es, ax
               
                push word ptr ds:[0]
                pop word ptr es:[9 * 4]
               
                push word ptr ds:[2]
                pop word ptr es:[9 * 4 + 2]
               
                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:[0]
                               
                push ax
                push es
                push ds
              
               
                in al, 60h

                cmp al, 1
                jne good
               
                inc byte ptr es:[160 * 12 + 40 * 2 + 1]
               
good:
                pop ds
                pop es
                pop ax
                iret
               
code ends
end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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:[0]                ;双字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:[160 * 12 + 40 * 2 + 1]        ;变色
               
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,此时栈内清空,模拟中断完成
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-8 10:29:13 | 显示全部楼层
楼主88行的ax要改成ah,或者数据改成1111110011111111b
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-8 20:02:39 | 显示全部楼层
Aslcwd 发表于 2019-5-8 09:16
int9段我有疑问
push了ax、es、ds,再pushf两次,pop,push、popf,call dw
那么栈中内容,低到高,存着i ...

2019-05-08_19-30-34.png

这里面这个call dword ptr ds:[0]是用来模拟int 9 命令的int 9 命令的运作原理是
绘图1.jpg
所以在int 9 结束的时候已经把 你所说的 ip cs pushf都已经释放了所以不存在隔着的情况
在这里你指出的那个and ax,11111100b那个是我错了这个应该是ah我应该改正
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-10 16:54:01 | 显示全部楼层
奥普瓯江 发表于 2019-5-8 20:02
这里面这个call dword ptr ds:[0]是用来模拟int 9 命令的int 9 命令的运作原理是

所以在int 9 结 ...

call的命令发出,其实是去执行真正的int 9去了,执行完毕还要iret,回到call下面那一行是吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-11 10:43:56 | 显示全部楼层
Aslcwd 发表于 2019-5-10 16:54
call的命令发出,其实是去执行真正的int 9去了,执行完毕还要iret,回到call下面那一行是吗?

嗯嗯是的,执行call下面的 in al, 61h
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-1 20:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表