什么是 i.h.ah、o.h.ah 和 int86?
What is i.h.ah, o.h.ah and int86?
我想了解一个获取箭头键的程序。
这是代码:
int getkeys( )
{
union REGS i,o;
while(!kbhit( ));
i.h.ah=0;
int86(22,&i,&o);
return(o.h.ah);
}
谁能解释一下这段代码。它是获取方向键,但我没有获取此代码。
调用BIOS中断16h,函数00h,即"Read key press"。
当这个中断调用returns时,AH会包含按键的扫描码。
int86
表示 "call interrupt"。 22
是中断号(16h,表示十六进制的16)。
i
表示设置中断的输入寄存器。 AH包含函数调用号:0(还有其他调用:https://en.wikipedia.org/wiki/INT_16H)
o
表示中断设置的输出寄存器。 AH 被指定(由 BIOS)包含按下键的扫描码。
Turbo-C/C++的int86
函数用于对DOS和BIOS服务进行系统中断调用。 REGS
联合是一种寻址中断上下文数据结构中的各个寄存器的方法。为了进行 DOS 或 BIOS 调用,您需要根据要进行的系统调用的要求在寄存器中设置值。 Ralph Brown's Interrupt List (RBIL) is an excellent source of DOS and BIOS system calls, their parameters and their return values. The Turbo-C documentation 这样定义 int86
:
Name int86 - general 8086 software interrupt interface
Usage int int86(int intr_num, union REGS *inregs,
union REGS *outregs);
Prototype in dos.h
Description Both of these functions execute an 8086 software
interrupt specified by the argument intr_num.
Before executing the software interrupt, both functions
copy register values from inregs into the registers.
In addition, int86x copies the segregs->x.ds and
segregs->x.es values into the corresponding registers
before executing the software interrupt. This feature
allows programs that use far pointers, or that use a
large data memory model, to specify which segment is
to be used during the software interrupt.
After the software interrupt returns, both functions
copy the current register values to outregs, copy the
status of the system carry flag to the x.cflag field
in outregs, and copy the value of the 8086 flags register
to the x.flags field in outregs. In addition, int86x
restores DS, and sets the segregs->es and segregs->ds
fields to the values of the corresponding segment
registers.
If the carry flag is set, it indicates that an error
occurred.
int86x allows you to invoke an 8086 software interrupt
that takes a value of DS different from the default data
segment, and/or that takes an argument in ES.
Note that inregs can point to the same structure that
outregs points to.
Return value int86 and int86x return the value of AX after completion
of the software interrupt. If the carry flag is set
(outregs->x.cflag != 0), indicating an error, these
functions set _doserrno to the error code.
int86
获取要调用的中断号和两个 REGS
联合指针。第一个包含进入中断处理程序时需要设置的值,第二个是检索中断返回的寄存器值的方法。
Turbo-C/C++ 对 REGS
的定义类似于:
struct WORDREGS {
unsigned int ax, bx, cx, dx, si, di, cflag, flags;
};
struct BYTEREGS {
unsigned char al, ah, bl, bh, cl, ch, dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
union的h
部分只是简单的寻址16位寄存器的高低8位寄存器的机制AX,BX、CX 和 DX 而不是通过 x
通过完整的 16 位寄存器。此代码:
i.h.ah=0;
只是将AH寄存器(AX的高8位寄存器)设置为0,传入int86
功能。此代码:
int86(22,&i,&o);
正在调用软件中断 22 (0x16)。如果您查看 RBIL Int 0x16/AH=x00
,您会发现它是 BIOS 调用:
KEYBOARD - GET KEYSTROKE
AH = 00h
Return:
AH = BIOS scan code
AL = ASCII character
您将看到此 BIOS 调用 returns AH 和 AL 中按下的下一个字符的 BIOS 扫描码是ASCII码。
行:
return(o.h.ah);
returns从getkeys
按下的字符的BIOS扫描码
注意:代码while(!kbhit( ));
会循环等待,直到检测到按键按下。 Int 0x16/AH=0x00 调用用于检索该按键的 BIOS 扫描代码。
我想了解一个获取箭头键的程序。 这是代码:
int getkeys( )
{
union REGS i,o;
while(!kbhit( ));
i.h.ah=0;
int86(22,&i,&o);
return(o.h.ah);
}
谁能解释一下这段代码。它是获取方向键,但我没有获取此代码。
调用BIOS中断16h,函数00h,即"Read key press"。
当这个中断调用returns时,AH会包含按键的扫描码。
int86
表示 "call interrupt"。 22
是中断号(16h,表示十六进制的16)。
i
表示设置中断的输入寄存器。 AH包含函数调用号:0(还有其他调用:https://en.wikipedia.org/wiki/INT_16H)
o
表示中断设置的输出寄存器。 AH 被指定(由 BIOS)包含按下键的扫描码。
Turbo-C/C++的int86
函数用于对DOS和BIOS服务进行系统中断调用。 REGS
联合是一种寻址中断上下文数据结构中的各个寄存器的方法。为了进行 DOS 或 BIOS 调用,您需要根据要进行的系统调用的要求在寄存器中设置值。 Ralph Brown's Interrupt List (RBIL) is an excellent source of DOS and BIOS system calls, their parameters and their return values. The Turbo-C documentation 这样定义 int86
:
Name int86 - general 8086 software interrupt interface Usage int int86(int intr_num, union REGS *inregs, union REGS *outregs); Prototype in dos.h Description Both of these functions execute an 8086 software interrupt specified by the argument intr_num. Before executing the software interrupt, both functions copy register values from inregs into the registers. In addition, int86x copies the segregs->x.ds and segregs->x.es values into the corresponding registers before executing the software interrupt. This feature allows programs that use far pointers, or that use a large data memory model, to specify which segment is to be used during the software interrupt. After the software interrupt returns, both functions copy the current register values to outregs, copy the status of the system carry flag to the x.cflag field in outregs, and copy the value of the 8086 flags register to the x.flags field in outregs. In addition, int86x restores DS, and sets the segregs->es and segregs->ds fields to the values of the corresponding segment registers. If the carry flag is set, it indicates that an error occurred. int86x allows you to invoke an 8086 software interrupt that takes a value of DS different from the default data segment, and/or that takes an argument in ES. Note that inregs can point to the same structure that outregs points to. Return value int86 and int86x return the value of AX after completion of the software interrupt. If the carry flag is set (outregs->x.cflag != 0), indicating an error, these functions set _doserrno to the error code.
int86
获取要调用的中断号和两个 REGS
联合指针。第一个包含进入中断处理程序时需要设置的值,第二个是检索中断返回的寄存器值的方法。
Turbo-C/C++ 对 REGS
的定义类似于:
struct WORDREGS {
unsigned int ax, bx, cx, dx, si, di, cflag, flags;
};
struct BYTEREGS {
unsigned char al, ah, bl, bh, cl, ch, dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
union的h
部分只是简单的寻址16位寄存器的高低8位寄存器的机制AX,BX、CX 和 DX 而不是通过 x
通过完整的 16 位寄存器。此代码:
i.h.ah=0;
只是将AH寄存器(AX的高8位寄存器)设置为0,传入int86
功能。此代码:
int86(22,&i,&o);
正在调用软件中断 22 (0x16)。如果您查看 RBIL Int 0x16/AH=x00
,您会发现它是 BIOS 调用:
KEYBOARD - GET KEYSTROKE AH = 00h Return: AH = BIOS scan code AL = ASCII character
您将看到此 BIOS 调用 returns AH 和 AL 中按下的下一个字符的 BIOS 扫描码是ASCII码。
行:
return(o.h.ah);
returns从getkeys
注意:代码while(!kbhit( ));
会循环等待,直到检测到按键按下。 Int 0x16/AH=0x00 调用用于检索该按键的 BIOS 扫描代码。