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

DrC*_*ore 1 x86 assembly interrupt

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

mov al, 0x10
int al    ; you can't do this for some reason
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*nau 6

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

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

大多数用于 DOS 的 C 编译器都提供了一个库函数,允许执行等效的int al.

这以以下方式工作:

在实模式下,一条int指令等于 apushf后跟一个远call到中断处理程序。

但是,“远”call只不过是将下一条指令的“远”地址(csip)压入堆栈并执行跳转。(“near”调用只会压入ip。) Aretf将从堆栈中弹出ipcs并跳转到该地址。

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

所以要进入中断,首先要执行以下代码:

  pushf
  push cs       # Leave this line out if "call helper" is a "far" call
  call helper
Run Code Online (Sandbox Code Playgroud)

进入函数时helper,堆栈如下所示:

Address (IP) of the instruction after "call helper"
Segment (CS) of the program
Flags
...
Run Code Online (Sandbox Code Playgroud)

这三个元素在一条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
Run Code Online (Sandbox Code Playgroud)

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
...
Run Code Online (Sandbox Code Playgroud)

retf指令的行为方式与前两个字已被“远”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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

performInt0:
    int 0
    ret
performInt1:
    int 1
    ret
performInt2:
    int 2
    ret
...
performInt255:
    int 255
    ret
Run Code Online (Sandbox Code Playgroud)

...然后call对所需的标签执行a 。

这当然总是可能的。