汇编器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,...
不是 mov
与 ds
作为目标寄存器。这是不同指令的方便表示法。见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 汇编器不同?