You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.code16与.code32的区别及i386保护模式相关执行疑问

i386保护模式与.code16/.code32相关问题解答

1. 保护模式下执行.code16代码是否有效?

分两种情况:

  • 如果当前代码段是16位保护模式段(段描述符的D位设为0),.code16生成的代码可以正常执行,此时CPU按16位指令规则解码。
  • 如果当前是32位保护模式段(D位设为1),直接执行.code16代码会出错。因为.code16是按16位模式编码的指令,而32位模式下CPU默认按32位规则解码,会把16位指令识别成错误的32位指令,导致程序崩溃。

2. 汇编器生成的.code16与.code32机器码有何差异?

核心差异体现在默认操作数/地址大小、指令前缀、跳转偏移长度这几点:

  • 默认操作数与前缀:
    • .code16下,默认使用16位寄存器(如ax、bx),要使用32位寄存器(如eax、ebx)或32位操作数,需要加0x66前缀。
    • .code32下,默认使用32位寄存器,要使用16位寄存器或操作数,需要加0x66前缀。
  • 默认地址大小与前缀:
    • .code16下默认是16位寻址(比如用bx+si这种16位基址+变址),要使用32位寻址(如eax+ebx),需要加0x67前缀。
    • .code32下默认是32位寻址,要使用16位寻址需加0x67前缀。
  • 跳转指令偏移:
    • 近跳转(如jmp near):.code16下是2字节偏移,.code32下是4字节偏移。
    • 远跳转(如ljmp):.code16下是2字节段选择子+2字节偏移,.code32下是2字节段选择子+4字节偏移。

3. 设置CR0寄存器后、跳转前可执行.code16代码的原因是什么?

CR0的PE位置1只是开启了保护模式的硬件支持,但CPU的指令解码模式由当前代码段的**D位(默认操作数大小位)**决定。在执行远跳转前,我们仍处于原来的16位段(实模式下的段本质是隐含的16位描述符,D位为0),CPU依然按16位指令规则解码,所以.code16生成的代码能正常运行。只有当执行ljmp跳转到32位代码段时,CPU才会加载新的段描述符(D位为1),正式切换到32位指令解码模式。

4. .code16和.code32的具体含义是什么?

这两个是汇编器的伪指令,用来告诉汇编器生成对应模式下的指令编码:

  • .code16:让汇编器生成适配16位执行模式的机器码。默认用16位寄存器、16位寻址方式,跳转指令生成16位偏移;如果要使用32位操作数或寻址,会自动添加必要的前缀(0x66/0x67)。
  • .code32:让汇编器生成适配32位执行模式的机器码。默认用32位寄存器、32位寻址方式,跳转指令生成4字节偏移;如果要使用16位操作数或寻址,自动添加对应前缀。
    简单说,就是给汇编器指定“默认的操作数/地址大小”,让它生成符合对应模式解码规则的机器码。

内容的提问来源于stack exchange,提问作者Markity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:05:23