assembly - .code16 和 .code32 有什么区别

标签 assembly x86 x86-16 gnu-assembler protected-mode

我正在通过观看一些视频来学习对 i386 的系统核心进行编程。我知道一些有关进入保护模式的程序:

.code16文件中,首先我需要打开A20地址线并更改CR0寄存器,然后我需要ljmp 转换为 .code32 代码。

现在我正在思考 .code16 机器代码和 .code32 机器代码之间的差异

这些是我的问题:

  1. 在保护模式下使用.code16代码是否有效?
  2. 汇编程序生成的.code16机器码和.code32机器码有什么区别
  3. 我发现在设置CR0寄存器之后、ljmp之前执行.code16代码是有效的,这是为什么?
  4. 我的老师告诉我 .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 08mov ecx,[eax]当在 32 位模式下运行时,它会解释 66 67 8b 08mov 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?

在内部,段寄存器( csds ...)似乎大约有 80 位长,但程序员只能看到这 80 位中的 16 位。

cs 的“隐藏”位之一寄存器指定 CPU 执行 16 位还是 32 位代码。 (在保护模式下,该位是从GDT或LDT读取的。)

根据我在阅读所谓“虚幻模式”时所读到的一些信息,i80386 CPU内部的“实模式”和“保护模式”之间的主要区别似乎在于当改变段寄存器的值时,在两种模式下对段寄存器的修改是不同的。 (中断处理等方面也有差异...)

如果这是 true,则设置或清除 CR0 的位 0在更改段寄存器之前(通过执行 ljmpmov ds,ax ... 或中断),(几乎)没有任何影响。

关于assembly - .code16 和 .code32 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74603224/

相关文章:

assembly - x86 操作码编码 : sib byte

c - 为什么求和 floats 到一个 int temporary 运行比当一切都是 int 时慢得多?

assembly - 我怎样才能更有效地编写这段代码?

assembly - 使用 INT 21h (DOS) 和 8086 汇编读取数字

assembly - 对 10 个数字求和并在 NASM 中打印结果

assembly - 如何汇编RISC-V指令集的RVC(压缩指令)扩展?

linux - 准备加载内核

c - 在 Win32 上使用 GCC 向程序集符号添加前导下划线?

c# - .NET 的汇编程序库,将运行时变量字符串组装成机器代码以进行注入(inject)

assembly - 8086汇编-如何添加2个字节,其总和将大于一个字节