指令的格式及其操作尺寸

xiaoeryu Lv5

01. 80286的16位保护模式

  1. 80286的寄存器和8086有同样的寄存器
      2. 80286的描述符有48位
     {% asset_img 89ef06a022ca9dfcc82e9db73a4dbd5a.png 80286描述符格式 %}
      	3. 80286也引入了描述符, 描述符表, 描述符高速缓存器, 段选择子的概念
          {% asset_img 50daf97b92479e82b0a8e32a76b16a03.png  %}
      	4. 80286的地址线有24位可以寻址16M空间的任意地址, 但是只有16位偏移, 所以确定了段地址后只能在1M的空间内偏移
          {% asset_img 8a96c9a8dc8774e1d9b3161716de41f8.png  %}
          {% asset_img 7cafe51b7eda396fb20e58546a24b41f.png  %}

02. 16位处理器的指令操作尺寸

    1.指令的操作尺寸
    2.  描述符高速缓存器中的基地址在实模式和保护模式下是不同的:
        **实模式**: 是将段地址左移四位得到的
        **保护模式**: 来自段描述符高速缓存器, 段描述符的内容由段选择子带入段选择器中, 从描述符表中取出对应的描述符放入段描述符高速缓存器中	
    3. 16位处理器的操作数尺寸可以是8, 16位的, 有效地址的尺寸始终是16位

03. 32位处理器的指令操作尺寸

  • 32位处理器的操作数尺寸可以是8, 16, 32位的, 有效地址的尺寸可以是16位或32位的

04. x86的指令格式ModRM和偏移量部分

05. x86的指令格式-ModRM和偏移量部分

  • 转换汇编到数字编码

6. x86的指令格式-SIB部分

SIB字段格式:

07. x86的指令格式-指令前缀部分

  • 指令前缀:段超越前缀、总线封锁前缀、数据传送指令的重复前缀、操作尺寸反转前缀、地址尺寸反转前缀等等。指令最多有4个前缀。
  • 课后练习:

08. 处理器的默认操作尺寸和相关指令前缀

  • 处理器默认操作尺寸, 可以添加前缀66(数据), 67(地址)来反转操作尺寸(16or32)
  • 上节课后练习答案: 之前讲过的操作尺寸: 16位、32位操作尺寸: 默认操作尺寸: 所以上节习题中:
    1. 默认操作尺寸是16位时:
    2. 默认操作尺寸是32位时:
  • 前缀66用来反转操作数的尺寸
  • 前缀67用来反转有效地址的尺寸

09. 用伪指令bits生成16位和32位模块

  • 相同机器指令对应不同汇编指令:
  • 相同机汇编指令对应不同机器指令:
    bits 16		;也可写为[bits 16],若为第一条[bits 16]指令也可省略;
                ;因为默认使用[bits 16]编译程序
    mov ax, [bx+si]
    
    bits 32		;也可写为[bits 32]
    mov ax, [bx+si]

10、描述符和段描述符高速缓存器的D位

    1. 描述符的D/B位, 对于代码段来说(S=1, X=1), 此位为D, 为0表示16位操作尺寸, 为1表示32位操作尺寸.

当描述符进入高速缓存器, 会设置高速缓存器的D位处理器根据此位来设置处理器的默认操作尺寸
当程序加电复位时, 处理器的默认操作尺寸是16位

11. 进入保护模式并切换到32位模块使用32位默认操作尺寸

    ;创建#1描述符,保护模式下的代码段描述符
    mov dword [bx+0x08],0x7c0001ff     
    mov dword [bx+0x0c],0x00409800   
  • 段基地址: 0x00007C00
  • 段界限: 0x0001FF
  • G位: 为0表示段界限的粒度是byte, 段的大小为: 0x1FF + 1 = 0X2000 = 512字节
  • S位: 为1表明是代码段
  • X位: 为1表明可执行
  • P位: 为1表示段是存在的
  • D/B位: 为1表明是32位的默认操作尺寸
    直接绝对原转移指令: 在保护模式和实模式下的区别
    ;以下进入保护模式
    jmp 0000000000010_0_00B:flush
    bits 32
    
flush:
    mov cx,00000000000_10_000B		;加载数据段选择子(0x10)
    mov ds,cx
    
    ;以下在屏幕上显示"Protect mode OK." 
    mov byte [0x00],'P'  
    mov byte [0x02],'r'
    mov byte [0x04],'o'

此时是在保护模式下, 默认操作尺寸是16位还未切换成32位。
通过描述符索引取出索引号为2的描述符存入高速缓存器中再用里面的基地址+偏移来算出要跳转的线性地址,线性地址 = 基地址(0x7c00) + 段内偏移量(flush)

执行这条jmp之后CS段选择器被修改, CS的描述符高速缓存器内容也被新的描述符刷新
因为在进入jmp指令之前很多指令已经进入了流水线按16位的默认操作尺寸进行译码的. 所以在使用bits 32改变了默认操作尺寸之后, 那些指令是错误的. 但是jmp指令执行之后会清空流水线, 再按32位默认尺寸重新填充流水线译码.
在执行jmpf之前, 可以看到这些指令对于写显存字符来说明显是不正确的

在执行jmpf指令之后, 可以看到当前处理器的默认操作尺寸是32位

此时再查看后面的指令流水线的译码就可以看到跟我们的汇编代码是一样的了

从此可以看出处理器的当前默认操作尺寸确实会影响指令的译码和执行.

  • 标题: 指令的格式及其操作尺寸
  • 作者: xiaoeryu
  • 创建于 : 2022-12-11 22:41:00
  • 更新于 : 2023-10-03 12:59:18
  • 链接: https://github.com/xiaoeryu/2022/12/11/23-指令的格式及其操作尺寸/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论