汇编器mov问题

Posted

技术标签:

【中文标题】汇编器mov问题【英文标题】:Assembler mov issue 【发布时间】:2010-09-11 07:14:29 【问题描述】:

我有下一个代码:

mov  ax,@data
mov  ds,ax

为什么我不能这样写?

mov ds,@data

所有来源:

   .MODEL small
   .STACK 100h
   .DATA
   HelloMessage DB 'Hello, world',13,10,'$'
   .CODE 
   .startup
   mov  ax,@data
   mov  ds,ax
   mov  ah,9
   mov  dx,OFFSET HelloMessage
   int  21h
   mov  ah,4ch
   int  21h
   END

谢谢!

【问题讨论】:

【参考方案1】:

您不能,因为指令集不包含执行此操作的指令。它只是 x86 的众多特性之一。

这些限制对于汇编语言来说是相当正常的。大多数架构都包含一些经过特殊处理的寄存器(例如处理器状态字),但通常少于 x86 架构。

不为所有可能的移动提供指令的原因是为了减小指令集的大小,以便指令占用更少的内存。总体而言,分两步执行很少需要的动作会更有效。

【讨论】:

+1 您也可以说,无法使用标准mov 指令之一修改ds 的原因是,在大多数指令中只保留了3 位来编码目标寄存器,并且 ax,bx,cx,dx,si,di,sp,bp 已经使用了所有可用的可能性。但这会简化一些事情。 是的,这是保持说明小规模的具体设计决策。 在那种情况下,mov ds,ax 是从哪里来的呢?我很确定这是一个mov,以ds 作为目标寄存器;)你有一个合理的论点,我只是在玩! @Lazarus mov ds,... 不是 movds 作为目标寄存器。这是不同指令的方便表示法。见pdos.csail.mit.edu/6.828/2004/readings/i386/MOV.htm @Pascal Cuoq :正如我所说,你的论点是正确的,我正在玩......或者你是在你到达句子的那部分之前到达你的分支,还是你只是选择忽略它。【参考方案2】:

作为“ax”的通用寄存器旨在保存指向数据的 16 位数字(在您的情况下是 DATA 内的字符串)

因此,如果您尝试将数据直接传递到特殊寄存器(此处为 ds 或数据段),它将无法正常工作,因为它不知道以这种方式接受数据。因此,我们首先获取该“数字”或数据开始的内存位置点并将该点传递给 ds 寄存器。

【讨论】:

【参考方案3】:

我不是专家,但这就是我理解这种约束的工作方式。

段寄存器用于控制寄存器指令使用哪个内存段,因此您最不想做的就是从内存位置加载段寄存器(在本例中为数据段寄存器) .修改 DS 的行为可能会导致正在读取的内存位置在更新 DS 的过程中发生变化,即加载到 DS 中的第一个位/字节现在导致它在读取其余部分之前指向另一个段。将值读入累加器 (AX) 或其他通用寄存器会更安全,因此现在值在加载到段寄存器时就在处理器中,因此在加载过程中值不会损坏。

【讨论】:

我不认为这是原因,因为在读取完整值后可以轻松更新 DS。 如果是这样的解释,就不会有像mul ax这样的指令,因为ax在被乘以它时可能会被“损坏”。 @starblue,如果处理器在将值加载到 DS 之前具有读取值的位置(比如mov ax,@Data 然后mov ds,ax),那么它可以很容易地以这种方式更新,但是设计效率可能只需将值加载到寄存器中即可。我并不是说我绝对正确,我是说这并非不可信。 @Pascal Cuoq :虽然我不同意我的解释可能是错误的,但我不同意您的验证。 mul ax 完全在处理器内执行,没有通过段寄存器访问内存。毕竟 AX 是累加器并且旨在完成狗的工作,很可能任何特殊情况都将应用于此寄存器,而不是其他任何情况。 @Lazarus 我打算使用更技术性的解释,即现代处理器在同一时刻存在相同寄存器的数十个版本,以及“指令之前的版本”和“指令之后的版本”指令”似乎不应该吓到设计人员,但这仍然会有点错误,因为指令集是在乱序执行之前设计的。事实上,您的回答与处理器功能的实际方式相去甚远,很难反驳。

以上是关于汇编器mov问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Solaris 汇编器生成的机器代码与这里的 GNU 汇编器不同?

汇编 MOV -2

汇编-MOV指令

将 GCC/ATT 风格的汇编器转换为 Visual Studio 汇编器?

使用 GNU 汇编器在 x86_64 中调用 printf

麻烦大家给我介绍一下汇编指令mov的用法吧