gpt4 book ai didi

assembly - 如何在 DOS 程序集中正确 Hook 中断 28h,并恢复它?

转载 作者:行者123 更新时间:2023-12-04 18:55:41 25 4
gpt4 key购买 nike

我正在尝试将中断 28h 的处理程序设置为我自己的例程,恢复所有涉及的寄存器和标志,并恢复原始中断处理程序。
我正在使用 NASM 汇编器,在 VirtualBox 中的 DOSBox 和 MS-DOS 6.22 下。

我想过调试,但在 TSR 程序上这样做听起来不太可能。我已经尝试将数据段推到代码段上,并保存原始数据段以供稍后恢复,但即使在恢复数据段后它似乎也挂起机器。

section .text   ;Code Section
org 100h ;DOS Executable Start
mov ah,35h ;Get Interrupt Vector
mov al,28h ;Of Interrupt 28h
int 21h ;Call DOS Kernel
push cs ;Push Code Segment
pop ds ;Onto Data Segment
mov [oldseg],es ;Save Old Interrupt Vector Segment
mov [oldoff],bx ;Save Old Interrupt Vector Offset
mov ah,25h ;Set Interrupt Vector
mov dx,resstart ;To Resstart
int 21h ;Call DOS Kernel
mov dx,resend ;Set Data Offset to Resend
sub dx,resstart ;Subtract Resstart
shr dx,4h ;Shift Right 4 Bits for Paragraph
inc dx ;One Extra Paragraph for PSP
mov ah,31h ;Terminate and Stay Resident
xor al,al ;Return Code
int 21h ;Call DOS Kernel

resstart: ;Resident Code Start
push ax ;Save AX
push es ;Save ES
push di ;Save DI
push cx ;Save CX
push ds ;Save DS
push dx ;Save DX
mov ah,00h ;Set Video Mode
mov al,13h ;To Mode 13h
int 10h ;Call BIOS Video
mov ax,0A000h ;VGA Segment
mov es,ax ;Stored in ES
xor di,di ;VGA Offset in DI
mov cx,0FA00h ;Fill Entire Screen
mov al,09h ;With Light Blue Color
rep stosb ;Repeat Store AL at ES:DI
mov ah,25h ;Set Interrupt Vector
mov al,28h ;Of Interrupt 28h
mov ds,[oldseg] ;Restore Old Interrupt Vector Segment
mov dx,[oldoff] ;Restore Old Interrupt Vector Offset
int 21h ;Call DOS Kernel
pop dx ;Restore DX
pop ds ;Restore DS
pop cx ;Restore CX
pop di ;Restore DI
pop es ;Restore ES
pop ax ;Restore AX
iret ;Return and Restore Flags
resend: ;Resident Code End

section .data
oldseg dw 0 ;Old Interrupt Vector Segment
oldoff dw 0 ;Old Interrupt Vector Offset

返回原中断向量地址,并将新的中断向量地址设置为“重启”后,程序应终止并驻留。在此之后,中断 28h 将自动触发,因为 DOS 无事可做,这将依次运行我的中断处理程序。

中断处理程序将视频模式设置为 13h,尝试用浅蓝色填充整个屏幕,恢复原始的中断 28h 处理程序,恢复所有涉及的寄存器和标志,并返回到 DOS。执行这个程序没有任何结果,系统甚至没有挂起。在运行设置视频模式 13h 并单独用蓝色填充整个屏幕的部分时,它工作得很好。

最佳答案

mov dx,resend ;Set Data Offset to Resend
sub dx,resstart ;Subtract Resstart
shr dx,4h ;Shift Right 4 Bits for Paragraph
inc dx ;One Extra Paragraph for PSP


在这个 .COM 程序中,您正在正确保存和设置中断向量。但是,您无法准确计算 DOS.TerminateAnd StayResident 函数要保留的段落数量。
inc dx需要四舍五入到最近的更高的段落。肯定不占PSP。这将需要 16 个段落,因为 PSP 有 256 个字节。

分配给这个 .COM 程序的内存以 PSP 开头,因此 DX计数也必须从那里开始。
mov     dx, resend 
shr dx, 4
inc dx
mov ax, 3100h ; DOS.TerminateAndStayResident
int 21h

提示 如果将此重新发送标签与段落边界对齐,则 inc dx不再需要。

如果您当前的代码在像 virtualbox 这样的模拟器中部分工作,那是因为您的程序以前占用的内存尚未被例如覆盖。程序 shell 。与 DOS 不同,仿真器可以从远处执行命令解释器。

the screen does fill with blue using virtualbox, though the system hangs



如果有人在我写东西的时候关灯,我也会挂!这就是您的处理程序在突然更改视频模式时所做的事情......

对于TSR程序,我们通常会跳过需要常驻的部分,这样一次性设置所占用的空间可以被系统回收。

您可以使用的另一个技巧是直接在将恢复向量的指令中写入旧中断向量的偏移量和段。处理程序中的段寄存器不再有问题。

这是我对你的程序的重写:
    org     100h
Start:
jmp Setup

MyInt28:
push ax
push es
push di
push cx
push ds
push dx
mov ax, 0013h ; BIOS.SetVideoMode
int 10h
mov ax, 0A000h
mov es, ax
xor di, di
mov cx, 64000/2
mov ax, 0909h
cld
rep stosw
PatchA:
mov ax, 0 ; Don't change this to 'xor ax,ax'
mov ds, ax
PatchB:
mov dx, 0 ; Don't change this to 'xor dx,dx'
mov ax, 2528h ; DOS.SetInterruptVector
int 21h
pop dx
pop ds
pop cx
pop di
pop es
pop ax
iret

Setup: ; Resident part ends here.
mov ax, 3528h ; DOS.GetInterruptVector
int 21h ; -> ES:BX
mov [PatchA + 1], es
mov [PatchB + 1], bx
mov dx, MyInt28
mov ah, 25h ; DOS.SetInterruptVector
int 21h
mov dx, (256+Setup-Start+15)/16
mov ax, 3100h ; DOS.TerminateAndStayResident
int 21h

关于assembly - 如何在 DOS 程序集中正确 Hook 中断 28h,并恢复它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56403333/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com