gpt4 book ai didi

基于寄存器值的汇编调用中断

转载 作者:行者123 更新时间:2023-12-05 09:11:12 26 4
gpt4 key购买 nike

我想在 NASM 中有一个中断,它调用的不是硬编码中断而是 int。在寄存器中。举个例子:

mov al, 0x10
int al ; you can't do this for some reason

因此,如果我将 0x10 存储在寄存器 al 中,那么我可以根据该寄存器中的内容调用中断。

有什么办法可以做到这一点吗?

最佳答案

Is there any way I could do this?

在没有自修改代码的 16 位“实模式”中:

大多数 DOS 的 C 编译器都提供了一个库函数,允许执行与 int al 等价的操作。

这是按以下方式工作的:

在实模式下,int 指令等于 pushf 后跟对中断处理程序的远 调用

但是,“远”调用只不过是将下一条指令的“远”地址(csip)推送到堆栈并执行跳跃。 (“near”调用仅压入 ip。) retf 将从堆栈中弹出 ipcs 并且跳转到那个地址。

中断处理程序的地址存储在地址0:(4*n)。

因此,要进入中断,您首先要执行以下代码:

  pushf
push cs # Leave this line out if "call helper" is a "far" call
call helper

当进入函数helper时,栈看起来是这样的:

Address (IP) of the instruction after "call helper"
Segment (CS) of the program
Flags
...

这三个元素在 int 指令之后在堆栈上。

helper 程序如下所示。

helper:
# Calculate BX = 4*AX
# (This can be done with less instructions on a modern CPU)
mov bl,al
mov bh,0
add bx,bx
add bx,bx
# Set DS to 0
xor ax,ax
mov ds,ax
# Push the segment part of the interrupt handler address
# to the stack
push word [bx+4]
# Push the offset part
push word [bx]
# Load all registers with the desired values
# TODO: Ensure all registers have the correct values
# Enter the interrupt
retf

retf 之前,堆栈将如下所示:

Address (IP) of the interrupt routine
Segment (CS) of the interrupt routine
Address (IP) of the instruction after "call helper"
Segment (CS) of the program
Flags
...

retf 指令的行为方式与前两个词已被“far”call 指令压入的方式相同:它将从中删除前两个词堆栈并跳转到这两个词描述的地址 - 这意味着:进入中断处理程序。

在中断处理程序结束时,最后 3 个字将从堆栈中弹出,并在 call helper 之后的指令处继续执行。

在具有自修改代码的 16 位“实模式”中:

这很简单:

    # AL contains the interrupt number
# Modify the "int" instruction, so "int 42" becomes
# "int 31" if the value of AL is 31.
mov cs:[theIntInstruction+1], al
# Load all registers with the desired values
# TODO: Ensure all registers have the correct values
# Now perform the "int" instruction
theIntInstruction:
int 42

自修改代码可能会产生负面影响。这意味着可能存在问题...

在(16 位或 32 位)“保护模式”中:

根据内存保护设置,您有机会写入“可执行”的内存。在这种情况下,您可以使用自修改代码。

如果您无法使用自修改代码,则不可能执行与 int al 等效的操作,除非您想执行以下操作:

performInt0:
int 0
ret
performInt1:
int 1
ret
performInt2:
int 2
ret
...
performInt255:
int 255
ret

...然后对所需标签执行调用

这当然总是可能的。

关于基于寄存器值的汇编调用中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60383360/

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