我正在通过观看一些视频来学习对 i386 的系统核心进行编程。我知道一些有关进入保护模式的程序:
在.code16
文件中,首先我需要打开A20地址线
并更改CR0
寄存器,然后我需要ljmp
转换为 .code32
代码。
现在我正在思考 .code16
机器代码和 .code32
机器代码之间的差异
这些是我的问题:
- 在保护模式下使用
.code16
代码是否有效? - 汇编程序生成的
.code16
机器码和.code32
机器码有什么区别 - 我发现在设置
CR0
寄存器之后、ljmp之前执行.code16
代码是有效的,这是为什么? - 我的老师告诉我
.code16
表示“生成指定为 16 位模式的代码”,而.code32
表示“指定为 32 位模式生成代码”,所以这是什么意思?
抱歉我的无知,我是这个领域的新手
最佳答案
What's the difference between .code16 machine code and .code32 machine code generated by assembler?
在 16 位模式(实模式和 16 位保护模式)和 32 位保护模式下,CPU 对代码字节的解释不同。
主要区别在于指令前缀66
的含义和67
(十六进制)反转:
在16位模式下,CPU默认使用16位寄存器和常量以及i8086类型的寻址模式。前缀66
告诉CPU使用32位寄存器和常量;前缀 67
告诉CPU使用i80386类型的寻址模式:
Program bytes Instruction understood by the CPU
8b 08 mov cx,[bx+si]
66 8b 08 mov ecx,[bx+si]
67 8b 08 mov cx,[eax]
66 67 8b 08 mov ecx,[eax]
在32位保护模式下,情况相反:
8b 08 mov ecx,[eax]
...
66 67 8b 08 mov cx,[bx+si]
"generate code specified to 16/32-bit mode" ... so what does that mean?
如果你的程序中有一行是 mov ecx,[eax]
,汇编器写 8b 08
在.code32
模式和 66 67 8b 08
在.code16
模式。
...因为CPU解释8b 08
如mov ecx,[eax]
当在 32 位模式下运行时,它会解释 66 67 8b 08
如mov ecx,[eax]
在 16 位模式下运行时。
Is it valid to use .code16 code in protect mode?
我已经写过有关“16 位保护模式”的文章。
实际上,不存在“16位保护模式”,而只有一种“保护模式”。在保护模式下,您可以在 GDT(或 LDT)中创建 16 位和 32 位描述符。
要在保护模式下执行 16 位代码,必须创建一个 16 位代码描述符(在 GDT 或 LDT 中)并执行 ljmp
到该代码。
(将 32 位 CPU 从保护模式切换回实模式需要在保护模式下执行 16 位代码。)
请注意,16 位代码(以及堆栈!)的描述符的大小必须仅为 64 KiB 及以下。这意味着您无法创建一个描述整个 4 GiB 内存的描述符(就像针对 32 位代码所做的那样),但可能需要为位于内存不同部分的代码创建多个描述符。
I found it is valid to execute .code16 code after I set CR0 register and before ljmp, that's why?
在内部,段寄存器( cs
、 ds
...)似乎大约有 80 位长,但程序员只能看到这 80 位中的 16 位。
cs
的“隐藏”位之一寄存器指定 CPU 执行 16 位还是 32 位代码。 (在保护模式下,该位是从GDT或LDT读取的。)
根据我在阅读所谓“虚幻模式”时所读到的一些信息,i80386 CPU内部的“实模式”和“保护模式”之间的主要区别似乎在于当改变段寄存器的值时,在两种模式下对段寄存器的修改是不同的。 (中断处理等方面也有差异...)
如果这是 true,则设置或清除 CR0
的位 0在更改段寄存器之前(通过执行 ljmp
、 mov ds,ax
... 或中断),(几乎)没有任何影响。
关于assembly - .code16 和 .code32 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74603224/