我正在使用Visual Studio构建一个控制台程序,我在这个C程序中使用了内联汇编指令,如图所示:code and error message。 对于那些看不到图片的人,我写的代码是:
void main() {
__asm {
mov ax, 0x4;
mov ds, ax; // 0xC0000005 error occurs while executing this instruction
xor eax, eax;
}
}
如您所见,我想为DS段寄存器分配一个值,并且我使用AX将值传送到DS寄存器(所以我不直接将值赋给DS寄存器)
编译和链接都可以,但是当我调试这个程序时,我得到错误代码:0xC0000005。在没有调试的情况下运行会导致同样的错误。
我正在使用Visual Studio的中文版,我不确定这个错误消息的确切翻译是什么,但它的粗略含义是: “在0x008e13c2处有一个未处理的异常:0xC0000005:读取0xffffffff时发生访问冲突。”
Q1:有人知道为什么会这样吗?我不能将随机值分配给DS寄存器吗?
顺便说一下,另一个问题是,当我将数字0到3分配给DS寄存器时,没有发生错误,但Visual Studio左下角的寄存器窗口显示 DS寄存器的值没有'已被更改。
Q2:为什么会这样?我是否已成功将值分配给DS寄存器?
任何帮助都会感激不尽。
答案 0 :(得分:4)
Visual Studio在Windows下运行,Windows将CPU切换为protected mode (PM)
在PM中,您不能再为选择器寄存器(如ds
)分配任何所需的值,而是操作系统会为您加载这些寄存器。
假设操作系统在这方面没有缺陷,并且Windows不是,则任何其他值 1 (但对于其他选择器寄存器上的那些)将触发异常。
如果你看过像
这样的代码mov ax, cs
mov ds, ax
mov ax, 0b800h
mov es, ax
mov ax, ...
mov ds, ax
然后是real mode代码,不再适合在Windows下运行 2 。
您可能需要考虑使用DOS模拟器(如DOSBox)和可生成16位可执行文件的汇编程序/编译器(如NASM,MASM,TASM或Turbo C )。
值00h - 03h在这方面很特殊,因为它们都代表 NULL选择器和
可以将NULL段选择器(值0000-0003)加载到DS,ES,FS和GS寄存器中而不会导致 保护例外。但是,任何后续尝试引用其相应段的段 register加载NULL值会导致一般保护异常(#GP)并且不会发生内存引用。
值04h没有引用NULL描述符,一旦你尝试用ds
设置它就会引发异常。
1 实际上,OS可以创建用户空间程序可访问的其他描述符,但假设它们的使用将等同于寄存器中已存在的描述符。因此,改变这些是没有意义的。
2 实际上,32位版本的Windows支持16位程序,但是,自Vista以来,64位版本不支持。 Visual Studio无法生成MZ exes,根据@RossRidge注释,您需要Visual C ++ 1.5或之前的版本。