Assembly 为什么要使用临时寄存器将值传递给段寄存器?

Assembly 为什么要使用临时寄存器将值传递给段寄存器?,assembly,x86,gnu-assembler,Assembly,X86,Gnu Assembler,我一直在关注编写汇编的几个示例,它们使用临时寄存器将立即数传递给段寄存器。为什么在将立即数放入段寄存器之前需要将其放入某个寄存器中? 示例: movw $0x7c00, %ax movw %ax, %ds ... ... movw $0x6000, %ax movw %ax, %ss 为什么不直接将立即数放入段寄存器中呢 movw $0x7c00, %ds ... movw $0x6000, %ss 因为英特尔没有提供这方面的说明(mov-seg,[ptr],mov-seg,imm16等)。

我一直在关注编写汇编的几个示例,它们使用临时寄存器将立即数传递给段寄存器。为什么在将立即数放入段寄存器之前需要将其放入某个寄存器中?
示例:

movw $0x7c00, %ax
movw %ax, %ds
...
...
movw $0x6000, %ax
movw %ax, %ss
为什么不直接将立即数放入段寄存器中呢

movw $0x7c00, %ds
...
movw $0x6000, %ss

因为英特尔没有提供这方面的说明(
mov-seg,[ptr]
mov-seg,imm16
等)。所以你必须这么做。结果很好,因为我们不再经常使用段/选择器

但这并不是没有希望。有带段的
lea
变体指令,可同时加载段和偏移量:

les di, [someptr]
(这实际上意味着:
di=[someptr];es=[someptr+2]

您还可以
/
弹出
,以避免寄存器交换,当然要以牺牲内存访问延迟为代价:

push immediate
pop  es

许多寄存器仅用于某一目的,对于某些操作不可交换(
bx
用于偏移,
cx
用于计数,
dx
用于高阶结果,
ax
用于结果)。因此,在机器代码文化中,使用临时寄存器并交换它们并不奇怪。

这是因为Intel获取或设置段寄存器的唯一指令是:

  • 获取寄存器->操作码:8C/r指令:MOV r/m16,Sreg说明:将段寄存器移动到r/m16。
  • 设置寄存器->操作码:8E/r指令:MOV Sreg,r/m16说明:将r/m16移动到段寄存器。
唯一的可能性是从寄存器或内存访问进行复制,例如:

MOV DS, AX
# or
MOV DS, WORD PTR [EAX]                   # or any memory addressing like bellow
MOV DS, WORD PTR [EAX + EBX *2 + 0x456]
.

有关汇编指令的压缩信息。

不允许立即移动到段寄存器。看,真正的答案是指令集空间很昂贵,因为只有这么多位,而每一条指令都需要晶体管来支持它。因此,CPU设计者不能提供所有可能的有用指令。因此,它们针对常见的活动进行优化(通过提供“方便”的指令),而忽略了支持在代码量或频率方面很少发生的活动的指令。“Mov立即到段”寄存器显然只需使用几条指令即可完成,而且很少需要,所以这就足够了。你应该预料到这一点。