x86实模式下访问32位寄存器/指令

参考:
https://blog.csdn.net/longintchar/article/details/50602851
https://forum.nasm.us/index.php?topic=991.0
https://www.linuxidc.com/Linux/2015-03/114346p4.htm

1、在16位实模式下,默认访问数据的大小是8位或者16位的;控制转移和内存访问时,偏移量也是16位的;
2、处理器在16位实模式下运行时,可以使用32位的寄存器,执行32位运算;

当处理器运行16位实模式下,既然把所有指令都看成16位的,那么怎么使用32位的寄存器,执行32位的运算呢?
答案是利用指令前缀0x66和0x67。指令前缀0x66用来选择非默认值的操作数大小,0x67用来选择非默认值的地址大小。

比如说:
1)指令码0x40在16位模式下对应的指令是 inc ax;
2)如果加上前缀0x66,也就是指令码66 40,当处理器在16位模式下运行,66 40对应的指令是 inc eax;

同理,如果处理器运行在32位模式下,处理器认为指令是32位的,如果加了0x66,那么就表示指令的操作数是16位的。

[bits 16] 
mov cx,dx      ;89 D1 
mov eax,ebx    ;66 89 D8 
 
[bits 32] 
mov cx,dx      ;66 89 D1 
mov eax,ebx    ;89 D8

#实际测试结果如下:

[BITS 16]
test1:
    mov bx, ax
    mov ebx, eax    	
	
[BITS 32]	
test2:
    mov bx, ax
    mov ebx, eax	
=================================================
Disassembly of section .text:

00000000 <test1>:
   0:	89 c3                	mov    %eax,%ebx
   2:	66 89 c3             	mov    %ax,%bx

00000005 <test2>:
   5:	66 89 c3             	mov    %ax,%bx
   8:	89 c3                	mov    %eax,%ebx

上述结果可见:
1)[BITS 32]场景下和预期一致,通过指令前缀0x66,在32位模式下访问16位寄存器;
2)[BITS 16]场景和预期不一致,第一句访问16位寄存器,反汇编结果却是访问32位寄存器;第二句访问32位寄存器,却插入指令前缀0x66,访问了16位寄存器。还没想明白为什么?

补充:上述[BITS 16]场景之所以和预期不一致,是因为objdump反汇编的时候参数不对。反汇编16位代码需要添加参数 -m i8086. 重新反汇编后结果如下,和预期一致。

00000000 <test1>:
   0:	89 c3                	mov    %ax,%bx
   2:	66 89 c3             	mov    %eax,%ebx

下述引用于 https://forum.nasm.us/index.php?topic=991.0
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值