编译器错误C2432:非法引用“标识符”中的16位数据

时间:2014-09-29 01:21:27

标签: c assembly operating-system system dos

所以我试图使用以下代码摘录转储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);
    }
}

提前致谢

1 个答案:

答案 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。