Execute a real-mode software interrupt
#include <x86/v86.h> int _intr_v86( int swi, struct _v86reg* regs, void* data, int datasize );
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
The _intr_v86() function executes the real-mode software interrupt specified by swi in virtual 8086 mode. This allows access to the ROM BIOS functions that are designed to run in 16-bit real mode. Two common examples are:
Interrupt | Description |
---|---|
int 10h | Video BIOS |
int 1ah | PCI |
BIOS calls (such as int 13h, disk I/O) that require hardware interrupts to be directed at their code aren't supported.
Upon entry to real mode, the registers are loaded from regs. The segment registers and any pointers should address a 2 KB communication area located at offset 0:800h in real memory. The buffer data of length datasize is copied to this area just before real mode is entered and copied back when the call completes. At this point regs is also updated to contain the values of the real-mode registers.
You should set the DS, ES, FS and GS segment registers to 0. The values in the CS:IP, and SS:SP registers are ignored and are set by the kernel. The stack provided is about 500 bytes in size.
The layout of real mode memory is described by the structure _v86_memory in <x86/v86.h>.
When a thread enters virtual 8086 mode, all threads in the system continue to be scheduled based upon their priority, including the calling thread. While in virtual 8086 mode, full access to IO ports and interrupt enable and disable are allowed. Only one thread may enter virtual 8086 mode at a time.
This function fails if the calling process doesn't have an effective user ID of root (euid 0).
#include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <errno.h> #include <x86/v86.h> struct _v86reg reg; int main( void ) { char buf[4]; /* Equipment call */ printf("int 12\n"); memset(®, 0, sizeof(reg)); _intr_v86(0x12, ®, NULL, 0); printreg(); sleep(5); /* Enter 40 column text mode */ printf("int 10 ah=00h al=00h\n"); memset(®, 0, sizeof(reg)); _intr_v86(0x10, ®, NULL, 0); printreg(); sleep(5); /* Enter 80 column text mode */ printf("int 10 ah=00h al=02h\n"); memset(®, 0, sizeof(reg)); reg.eax = 2; _intr_v86(0x10, ®, NULL, 0); printreg(); sleep(5); /* Write a string from memory */ printf("int 10 ah=13h al=00h\n"); strcpy(buf, "Hi!"); memset(®, 0, sizeof(reg)); reg.eax = 0x1300; reg.es = 0; reg.ebp = offsetof(struct _v86_memory, userdata); reg.ecx = strlen(buf); reg.edx = 0; reg.ebx = 0x0007; _intr_v86(0x10, ®, buf, strlen(buf)); printreg(); sleep(5); return EXIT_SUCCESS; } printreg() { printf("eax=%-8x ebx=%-8x ecx=%-8x edx=%-8x\n", reg.eax, reg.ebx, reg.ecx, reg.edx); printf("esi=%-8x edi=%-8x ebp=%-8x esp=%-8x\n", reg.esi, reg.edi, reg.ebp, reg.esp); printf(" ds=%-8x es=%-8x fs=%-8x gs=%-8x\n", reg.ds, reg.es, reg.fs, reg.gs); printf("efl=%-8x\n\n", reg.efl); }
Safety: | |
---|---|
Cancellation point | No |
Interrupt handler | No |
Signal handler | Yes |
Thread | Yes |