Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 实模式下的中断处理程序链接_C_Assembly_Interrupt Handling_Tasm_Real Mode - Fatal编程技术网

C 实模式下的中断处理程序链接

C 实模式下的中断处理程序链接,c,assembly,interrupt-handling,tasm,real-mode,C,Assembly,Interrupt Handling,Tasm,Real Mode,我试图钩住biosint13h,将我的自定义功能添加到其中,并劫持一些现有功能。 旧Int 13h向量存储在全局变量中。 当调用中断处理程序时,DS被设置为与调用者的原始数据段不匹配的值。因此,访问调用者的全局变量变成了一件令人头痛的事情 链接中断处理程序的最佳实践是什么 吊钩的安装方式如下: #ifdef __cplusplus # define INTARGS ... #else # define INTARGS unsigned bp, unsigned di, unsigned si

我试图钩住biosint13h,将我的自定义功能添加到其中,并劫持一些现有功能。 旧Int 13h向量存储在全局变量中。 当调用中断处理程序时,DS被设置为与调用者的原始数据段不匹配的值。因此,访问调用者的全局变量变成了一件令人头痛的事情

链接中断处理程序的最佳实践是什么

吊钩的安装方式如下:

#ifdef __cplusplus
#  define INTARGS ...
#else
#  define INTARGS unsigned bp, unsigned di, unsigned si,\
                  unsigned ds, unsigned es, unsigned dx,\
                  unsigned cx, unsigned bx, unsigned ax
#endif

void interrupt (far *hackInt13h)(INTARGS) = NULL;
void interrupt (far *biosInt13h)(INTARGS) = (void interrupt (far *)(INTARGS))0xDEADBEEF;

void main(void)
{
  struct REGPACK reg;

  biosInt13h = getvect(0x13);
  hackInt13h = int13h;

  setvect(0x13, hackInt13h);

  // Calling CAFE
  reg.r_ax = 0xCAFE;
  intr(0x13, &reg);
  printf("Cafe returned: 0x%04x\n", reg.r_ax);

  // Resetting FDD just to check interrupt handler chaining
  reg.r_ax = 0;
  reg.r_dx = 0;
  intr(0x13, &reg);
  printf("CF=%i\n", reg.r_flags & 0x01);

  setvect(0x13, biosInt13h);
}

Int 13h钩代码:

    P286
    .MODEL TINY

_Data   SEGMENT PUBLIC 'DATA'
    EXTRN _biosInt13h:FAR
_Data   ENDS


_Text   SEGMENT PUBLIC 'CODE'
    PUBLIC _int13h
_int13h PROC FAR
    pusha
    cmp AX,0CAFEh
    jnz chain
    popa
    mov AX, 0BEEFh
    iret
chain:
    popa
    call    far ptr [_biosInt13h]   ; <-- at this moment DS points to outer space
                                    ;     and _biosInt13h is not valid
_int13h ENDP
_Text   ENDS
    END
P286
.微型模型
_数据段公共“数据”
EXTRN_biosInt13h:远
_数据端
_文本段公共“代码”
公共_int13h
_int13h PROC FAR
普沙
cmp AX,0CAFEh
jnz链
波帕
mov AX,0BEEFh
艾雷特
链:
波帕

呼叫远ptr[_biosInt13h] 谢谢你们,我找到了解决办法

我错过的第一件事是将变量移动到代码段并显式指定它

第二种方法是使用hacked(栈上推送)返回地址和
retf
,而不是
call
,后者在栈上添加真实的返回地址

无需显式地
pushf
,因为标记已在
int
之后的堆栈上。无论是在我的处理程序中还是在链接的处理程序中,标记都将在iret上弹出

    P286
    .MODEL TINY

_Text   SEGMENT PUBLIC 'CODE'
    EXTRN _biosInt13h:FAR ; This should be in CODE 'cause CS is only segreg reliable
    PUBLIC _int13h
_int13h PROC FAR
    pusha
    cmp AX, 0CAFEh
    jnz chain
    popa
    mov AX, 0BEEFh
    iret
chain:
    popa
    push    word ptr cs:[_biosInt13h + 2]   ; Pushing chained handler SEG on stack
    push    word ptr cs:[_biosInt13h]       ; Pushing chained handler OFFSET on stack
    retf                        ; ...actually this is JMP FAR to address on stack
_int13h ENDP
_Text   ENDS
    END

谢谢你们,我找到了解决办法

我错过的第一件事是将变量移动到代码段并显式指定它

第二种方法是使用hacked(栈上推送)返回地址和
retf
,而不是
call
,后者在栈上添加真实的返回地址

无需显式地
pushf
,因为标记已在
int
之后的堆栈上。无论是在我的处理程序中还是在链接的处理程序中,标记都将在iret上弹出

    P286
    .MODEL TINY

_Text   SEGMENT PUBLIC 'CODE'
    EXTRN _biosInt13h:FAR ; This should be in CODE 'cause CS is only segreg reliable
    PUBLIC _int13h
_int13h PROC FAR
    pusha
    cmp AX, 0CAFEh
    jnz chain
    popa
    mov AX, 0BEEFh
    iret
chain:
    popa
    push    word ptr cs:[_biosInt13h + 2]   ; Pushing chained handler SEG on stack
    push    word ptr cs:[_biosInt13h]       ; Pushing chained handler OFFSET on stack
    retf                        ; ...actually this is JMP FAR to address on stack
_int13h ENDP
_Text   ENDS
    END


通常的解决方案是将变量移动到代码段中,这样您就可以使用
call far ptr[cs:_biosInt13h]
或根据需要设置段,检索指针,将其放在堆栈上,恢复段,然后执行
retf
跳转到BIOS中断处理程序。请注意,由于中断处理程序除了返回地址外还会弹出标志,因此代码将按原样崩溃。如果您使用的是tiny model,则可以对far调用使用
cs
段覆盖。但是,您需要将其更改为远跳转,或者在远调用之前添加
pushf
。如果您没有返回到处理程序并且正在尾调用旧的处理程序,那么您可以使用
jmp远ptr[cs:_biosInt13h]
。然后,
iret
将由旧的中断处理程序直接执行。只有在微型模型中执行此操作并最终构建COM程序时,CS段重写才会起作用,否则您必须显式加载DS寄存器,其中包含特定于所用模型的段。@MichaelPetch您只需将变量与访问它的中断函数位于同一段中。通常的解决方案是将变量移动到代码段中,以便使用
调用far ptr[cs:_biosInt13h]
或根据需要设置段,检索指针,将其放在堆栈上,还原段,然后执行
retf
跳转到BIOS中断处理程序。请注意,由于中断处理程序除了返回地址外还会弹出标志,因此代码将按原样崩溃。如果您使用的是tiny model,则可以对far调用使用
cs
段覆盖。但是,您需要将其更改为远跳转,或者在远调用之前添加
pushf
。如果您没有返回到处理程序并且正在尾调用旧的处理程序,那么您可以使用
jmp远ptr[cs:_biosInt13h]
。然后,
iret
将由旧的中断处理程序直接执行。只有在微型模型中执行此操作并最终构建COM程序时,CS段重写才会起作用,否则您必须显式加载DS寄存器,其中包含特定于所用模型的段。@MichaelPetch您只需将变量与访问它的中断函数位于同一段中。为什么使用
push
push
retf
。你就不能做一个间接跳远吗。试着记住TASM的语法。也许
jmp-dword-ptr-cs:[\u-biosInt13h]
?您只需编写
jmp[\u-biosInt13h]
,而不必编写RETF内容,但是您需要将
\u biosInt13h
正确地声明为
EXTERN\u biosInt13h:DWORD
,并且您需要告诉汇编程序它不能假设DS和ES指向与
\u TEXT
相同的段,而
假设DS:NOTHING,ES:NOTHING
@MichaelPetch也可以工作
push
push
retf
的灵感来源于MS-DOS 5.0启动记录的反汇编。@RossRidge远指针的大小与DWORD相同,但似乎最好使用适当的类型,而不是相同长度的类型。因此我更喜欢
jmp-far-ptr
而不是
jmp-dword-ptr
No,远指针的合适类型是dword。。FAR是您直接跳转到的FAR标签的适当类型。DWORD是您间接跳转到的远指针的合适类型。为了明确起见,我要说的是,您不应该使用
jmp-far-ptr
,因为这将是一个直接跳转,如果您正确声明
\u biosInt13h
,则不需要使用
jmp-dword-ptr
。DWORD和FAR的大小相同,但与跳转和调用指令一起使用时不能互换。DWORD是获得间接跳转所需的类型。为什么使用
push
push
retf
。你就不能做一个间接跳远吗。试着记住TASM的语法。也许
jmp-dword ptr-cs:[\u-biosInt13h]
?您可以只编写
jmp[\u-biosInt13h]
而不是RETF内容,但是您需要将
\u-biosInt13h
正确地声明为
EXTERN\u-biosInt13h:dword
,并且您需要告诉汇编程序它不能假设DS和ES指向同一个点