简体   繁体   中英

Compiler Error C2432 : illegal reference to 16-bit data in 'identifier'

So I was trying to dump the contents of the Interrupt Vector Table on 32 bit Widows 7 using the following code excerpt. It does not compile with Visual Studio as Visual Studio has probably withdrawn support for 16 Bit compilation. I built it in Pelles C, however the executable would crash when I try to run it. The problem, as I figured from some research over the internet, has to do with the 16 bit register reference (to ES). I do not however clearly understand the issue. I would really appreciate if someone could help me out with getting this to work on 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);
    }
}

Thanks in advance

The issue with es (or any segment register) is that in real mode (which your dos is "faking" with vm86), the value in the segment register is multiplied by 16 and added to the offset to get a linear address - which is the physical address. In protected mode (your win32) the segment registers are "selectors", an index into an array of structures (descriptors) containing (among other things) a "base" which is added to an offset to get a linear address. The value zero is explicitly the invalid selector, so it crashes. The good news is that the "base" of most segment registers ( fs an exception) is zero, so you can address the memory you want without touching es .

The bad news is virtual memory. Paging is enabled, so the linear address calculated by base + offset may not be a physical address. If you're lucky, your OS may have kindly "identity mapped" low memory, so that linear memory equals physical memory. If you're really lucky, your OS may let you at it from user code.

Try removing all references to es and see what happens. The results, if any, would be more recogizable in hex (%x), not decimal. Your best bet might be to do the whole thing in 16-bit and forget win32.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM