所以我试图使用以下代码摘录转储32位Widows 7上的中断向量表的内容。它不能用Visual Studio编译,因为Visual Studio可能已经取消了对16位编译的支持。我在Pelles C中构建它,但是当我尝试运行时,可执行文件会崩溃。正如我从互联网上的一些研究中得知的那样,问题与16位寄存器参考(与ES)有关。但我并不清楚这个问题。我真的很感激,如果有人可以帮助我在win32上工作
#include <stdio.h>
#define WORD unsigned short
#define IDT_001_ADDR 0 // start address of the first IVT vector
#define IDT_255_ADDR 1020 // start address of the last IVT vector
#define IDT_VECTOR_SZ 4 // size of the each IVT vector
int main(int argc, char **argv) {
WORD csAddr; // code segment of given interrupt
WORD ipAddr; // starting IP for given interrupt
short address; // address in memory (0-1020)
WORD vector ; // IVT entry ID (0..255)
vector = 0x0;
printf("n-- -Dumping IVT from bottom up ---n");
printf("Vector\tAddresst\n");
for(address=IDT_001_ADDR; address<=IDT_255_ADDR; address=address+IDT_VECTOR_SZ,vector++) {
printf("%03d\t%08d\t", vector , address);
// IVT starts at bottom of memory, so CS is always 0x0
__asm {
PUSH ES
mov AX, 0
mov ES,AX
mov BX, address
mov AX, ES:[BX]
mov ipAddr ,AX
inc BX
inc BX
mov AX, ES:[BX]
mov csAddr, AX
pop ES
};
printf("[CS:IP] = [%04X,%04X]n" ,csAddr, ipAddr);
}
}
提前致谢
答案 0 :(得分:1)
es
(或任何段寄存器)的问题是在实模式下(你的dos是&#34;假装&#34;用vm86),段寄存器中的值乘以16并且添加到偏移量以获得线性地址 - 这是物理地址。在保护模式(你的win32)中,段寄存器是&#34;选择器&#34;,一个结构数组(描述符)的索引,包含(其中包括)&#34; base&#34;将其添加到偏移量以获取线性地址。零值显然是无效选择器,因此崩溃。好消息是&#34; base&#34;大多数段寄存器(fs
异常)为零,因此您可以在不触及es
的情况下寻址所需的内存。
坏消息是虚拟内存。启用了寻呼,因此由base + offset计算的线性地址可能不是物理地址。如果你很幸运,你的操作系统可能会有一个&#34;身份映射&#34;低内存,使线性内存等于物理内存。如果您真的很幸运,您的操作系统可能会通过用户代码让您使用它。
尝试删除对es
的所有引用,看看会发生什么。结果(如果有的话)在十六进制(%x)中更易于识别,而不是十进制。你最好的选择可能是用16位完成整个事情而忘记win32。