You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TASM中检测INT 1单步中断是否发生在IMUL指令执行前的实现咨询

TASM中检测INT 1单步中断是否发生在IMUL指令执行前的实现咨询

嘿,我来帮你搞定这个问题!你现在的核心需求是在INT1单步中断的处理程序里,判断当前触发中断后即将执行的指令是不是IMUL cl,然后分别输出对应的信息对吧?下面我一步步给你讲清楚怎么实现:

第一步:搞清楚IMUL cl的机器码

要判断指令类型,首先得知道它对应的机器码。你用的IMUL cl是单操作数8位寄存器版本的IMUL,它的机器码是两个字节:0xF6(第一字节,操作码前缀)和0xC1(第二字节,ModR/M字段,用来指定操作数是cl寄存器)。

第二步:修改中断处理程序,读取并判断机器码

你的中断处理程序已经拿到了返回地址(也就是下一条要执行的指令地址),现在需要读取这个地址的前两个字节,和IMUL的机器码对比。具体修改如下:

首先,在.data段添加需要输出的IMUL相关提示字符串:

.data
PranNe  db "Not IMUL", 13, 10, "$"
; 新增IMUL相关提示
ImulMsg db "IMUL detected!", 13, 10
AddrMsg db "Address: $"
CodeMsg db 13, 10, "Machine Code: F6 C1$"
MnemonicMsg db 13, 10, "Mnemonic: IMUL$"
OperandMsg db 13, 10, "Operand: cl$", 13, 10, "$"

然后,修改ApdorokPertr中断处理程序里的判断逻辑:

PROC ApdorokPertr
;put register values ​​on the stack
PUSH    ax
PUSH    bx
PUSH    dx
PUSH    bp
PUSH    es
PUSH    ds

MOV ax, @data
MOV ds, ax

;In the DL register, we write the operation code of the command before which the INT was called
MOV bp, sp
ADD bp, 12
MOV bx, [bp]       ; bx = 返回地址的偏移量
MOV es, [bp+2]     ; es = 返回地址的段地址

; 读取指令的前两个字节:第一个字节存dl,第二个存dh
MOV dl, [es:bx]
MOV dh, [es:bx+1]

; 判断是否是IMUL cl(机器码F6 C1)
CMP dl, 0F6h
JNE NotImul
CMP dh, 0C1h
JNE NotImul

; 如果是IMUL,输出相关信息
; 先输出检测提示
MOV ah, 9
MOV dx, offset ImulMsg
INT 21h

; 输出地址(es:bx)
MOV ah, 9
MOV dx, offset AddrMsg
INT 21h
; 打印段地址es
MOV ax, es
CALL PrintHex
MOV dl, ':'
MOV ah, 2
INT 21h
; 打印偏移地址bx
MOV ax, bx
CALL PrintHex
MOV dl, 13
MOV ah, 2
INT 21h
MOV dl, 10
MOV ah, 2
INT 21h

; 输出机器码、助记符、操作数
MOV ah, 9
MOV dx, offset CodeMsg
INT 21h
MOV dx, offset MnemonicMsg
INT 21h
MOV dx, offset OperandMsg
INT 21h

JMP endd

NotImul:
; 不是IMUL,输出原信息
MOV ah, 9
MOV dx, offset PranNe
INT 21h

endd:
POP ds
POP es
POP bp
POP dx
POP bx
POP ax
IRET
ApdorokPertr ENDP

第三步:添加十六进制打印子程序(用来输出地址)

因为要打印指令的地址(段:偏移),需要一个把16位寄存器的值转换成十六进制字符串打印的子程序,你可以在.code段里添加这个子程序:

; 十六进制打印子程序:输入ax,输出ax的十六进制值
PrintHex PROC
    PUSH cx
    PUSH dx
    MOV cx, 4
PrintLoop:
    ROL ax, 4
    MOV dl, al
    AND dl, 0Fh
    ADD dl, '0'
    CMP dl, '9'
    JBE PrintChar
    ADD dl, 7h ; 转换为A-F
PrintChar:
    MOV ah, 2
    INT 21h
    LOOP PrintLoop
    POP dx
    POP cx
    RET
PrintHex ENDP

一些关键说明

  1. 单步中断的触发时机:INT1单步中断是在每条指令执行前触发的,所以当中断处理程序被调用时,栈里的返回地址就是下一条要执行的指令的地址,这正是我们需要检测的目标。
  2. 多字节指令处理:IMUL是双字节指令,所以必须读取前两个字节才能准确判断,只读第一个字节会和其他使用0xF6作为前缀的指令混淆。
  3. 寄存器保护:你的代码里已经正确保存和恢复了所有用到的寄存器,这很重要,不然会破坏主程序的执行状态。

现在把这些代码整合到你的原程序里,编译运行后,当单步中断触发在IMUL指令前时,就会输出IMUL的详细信息,其他时候输出"Not IMUL"。

备注:内容来源于stack exchange,提问作者lulzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 07:58:17