assembly .code16和.code32之间的区别是什么

piok6c0g  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(332)

我正在看一些视频学习i386的系统内核编程,我知道一些进入保护模式的步骤:
在一个.code16文件中,首先我需要打开A20 Address Line并更改CR0寄存器,然后我需要将ljmp转换成一个.code32代码。
现在,我正在考虑.code16机器代码和.code32机器代码之间的区别
以下是我的问题:
1.在保护模式下使用.code16代码是否有效?

  1. .code16机器码和汇编程序生成的.code32机器码有什么区别
    1.我发现在我设置CR0寄存器之后和ljmp之前执行.code16代码是有效的,这是为什么?
    1.我的老师告诉我.code16的意思是“生成指定为16位模式的代码”,.code32的意思是“生成指定为32位模式的代码”,那么这是什么意思呢?
    很抱歉我的无知,我是这方面的绿色
kognpnkq

kognpnkq1#

汇编程序生成的.code16机器码和.code32机器码有什么区别?
在16位模式(真实的模式和16位保护模式)和32位保护模式下,CPU对代码字节的解释不同。
主要区别在于指令前缀6667(十六进制)得含义相反:
在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]

“生成指定为16/32位模式的代码”...那么这是什么意思呢?
如果程序中有一行是mov ecx,[eax],汇编程序将以.code32模式写入8b 08,以.code16模式写入66 67 8b 08
...因为在32位模式下运行时,CPU将8b 08解释为mov ecx,[eax],而在16位模式下运行时,CPU将66 67 8b 08解释为mov ecx,[eax]
在保护模式下使用.code16代码是否有效?
关于“16位保护模式”我已经写过了。
实际上,不存在“16位保护模式”,只有一个“保护模式”。在保护模式下,您可以在GDT(或LDT)中创建16位和32位描述符。
要在保护模式下执行16位代码,必须创建一个16位代码描述符(在GDT或LDT中),并对该代码执行ljmp
(要将32位CPU从保护模式切换回真实的模式,需要在保护模式下执行16位代码。)
请注意,16位代码(以及堆栈)的描述符的大小必须小于等于64 KiB。这意味着您无法创建一个描述符来描述整个4 GiB内存(就像32位代码一样),但可能需要为位于内存不同部分的代码创建多个描述符。
我发现在设置CR 0寄存器之后和ljmp之前执行.code16代码是有效的,这是为什么?
在内部,段寄存器(csds...)* 看起来 * 大约为80位长,但这80位中只有16位对程序员可见。
cs寄存器的一个“隐藏”位指定CPU是执行16位还是32位代码。(在保护模式下,该位从GDT或LDT读取。)
根据我在阅读所谓的“虚幻模式”时所读到的一些信息,i80386 CPU内部的“真实模式”和“保护模式”之间的主要区别似乎是,当改变段寄存器的值时,段寄存器的“隐藏”位在两种模式中的修改方式不同。(中断处理等方面也有区别...)
如果为真,则设置或清除CR0的位0(几乎)没有任何影响,直到段寄存器被更改(通过执行ljmpmov ds,ax...或中断)。

相关问题