百科问答小站 logo
百科问答小站 font logo



汇编转换到机器码的时候,寄存器占几个字节? 第1页

  

user avatar   bei-ji-85 网友的相关建议: 
      

我发现了,写评论里是没人看的,那我就单独开一个答案:

以下仅限于x86架构(含64位)

通用寄存器(AX,CX,BX,DX,SP,BP,SI,DI)占3个bit,一共只有8个,通过段选择描述符里D位来确定是32位还是16位寄存器。

如果指令中包含w位,那么w位用于指定是CS.D里指定的位数(w==1),还是是8位寄存器(w==0)

66前缀用于指定是不是16位。

REX前缀里b位和r位(源寄存器、目的寄存器)用于控制扩展64位专有的寄存器(r8~r15)

所以,16/32位模式下,决定用哪个通用寄存器的是3bit(寄存器选择)+1(指令中的w位)+1(CS.D)

64位模式下,要另外算上REX前缀里的两位,和66前缀(可选)。

那么不计66前缀的情况下,需要6个bit表示一个寄存器,一共能表达64种寄存器。

对于一个x86的通用寄存器,一共有4个(不含AH/BH/CH/DH),8个通用寄存器一共有32种组合,因为有AH/BH/CH/DH的存在,所以一共是36个通用寄存器,但这四个特殊的寄存器无法在REX前缀下使用。

以上只通用寄存器。


段寄存器要看具体情况,在不支持FS/GS的场景里,占2bit,支持FS/GS的场景里,占3bit,因为编码的问题,段寄存器不能直接用立即数赋值。


其它寄存器见下表:

所以,一般来说,x86里明确指示寄存器的ID的编码,通常只有3个bit,其余都靠其它位置的标志位来控制。


因为寄存器ID只有3个bit,但寄存器的数量很多,所以汇编语言的翻译器要求汇编代码必须指定当前的默认操作数的位数。在Linux汇编里看到的就是类似code32 code64这些,这些东西会直接影响寄存器的编码方式。

另外,Intel手册里关于指令编码,只看第二卷的开头两章和结尾部分就可以了,大概只有300-400页的样子,很少,第二卷的全书有几千页,大部分都是讲指令细节的,如果不是专门搞这个的,没必要全看完。

补一张全图:



具体到指令的整体长度,x86指令构成如下:

legacy prefix+REX prefix+1~3B OpCode+ModRM/SIB+1/2/4B Addr + 1/2/4 Imm

其中legacy prefix包括前面说的66前缀,还有rep,段选择子,lock前缀等。

REX前缀目前只有1字节,在64位下使用。

opcode就是真正的指令,需要注意的是,有些寄存器编码是在opcode里进行的。

ModRM/SIB用于决定指令的操作对象是寄存器还是立即数还是内存地址。

最后两部分就是地址和立即数。

对于题主的问题,xorl和xorq分别是32位和64位指令,64位指令需要REX前缀,所以多一个字节。

MOV的问题,因为MOV有多种编码方式,所以需要看具体的二进制代码才能判断汇编器用了哪种方式编码,特别说明的是64位寄存器不一定需要完整的64位立即数。




  

相关话题

  为什么保护模式只能向更高特权级代码段转移控制? 
  C语言中, for 和 while 在汇编上有什么区别? 
  为什么 lea 会被用来计算? 
  进程的堆栈区和%esp的堆栈是否是一个概念? 
  有没有将c语言源代码转换成汇编语言的软件?有没有将python语言源代码转换成汇编语言的软件? 
  如何看待 2019 年 1 月 10 日发布的 Radeon Ⅶ ? 
  为什么英特尔x86等多数中央处理器不支持源操作数和目标操作数同时为内存的指令? 
  DOS 界面是如何制作的? 
  都说寄存器比内存快,但是为什么有些时候运行显示的是寄存器更慢? 
  为什么汇编mov指令不能用lock前缀? 

前一个讨论
最近网上有一段话,说是中国要建设北京到墨尔本的高铁,我知道这是谣言,但是有这种可能性吗?
下一个讨论
英特尔酷睿i系列架构求解?





© 2024-12-23 - tinynew.org. All Rights Reserved.
© 2024-12-23 - tinynew.org. 保留所有权利