汇编:在两个存储器地址之间移动

时间:2009-08-19 10:46:00

标签: assembly x86 instructions mov

我正在尝试学习汇编(所以请耐心等待),我在这一行上遇到编译错误:

mov byte [t_last], [t_cur]

错误是

error: invalid combination of opcode and operands

我怀疑这个错误的原因很简单,因为移动指令不可能在两个内存地址之间移动,但是半小时的谷歌搜索并且我无法确认这一点 - 是这样的吗?

另外,假设我是对的,这意味着我需要使用寄存器作为复制内存的中间点:

mov cl, [t_cur]
mov [t_last], cl

推荐使用的寄存器是什么(或者我应该使用堆栈)?

6 个答案:

答案 0 :(得分:26)

你的怀疑是正确的,你不能从记忆转移到记忆。

任何通用寄存器都可以。如果您不确定其中的内容并在完成后将其恢复,请记得推送寄存器。

答案 1 :(得分:6)

16位非常简单,只需执行以下操作:

     push     di
     push     si
     push     cx
     mov      cx,(number of bytes to move)
     lea      di,(destination address)
     lea      si,(source address)
     rep      movsb
     pop      cx
     pop      si
     pop      di

注意:推动&如果您需要保存寄存器的内容,则需要弹出窗口。

答案 2 :(得分:3)

还有一个MOVS命令,用于将数据从内存移动到内存:

MOV SI, OFFSET variable1
MOV DI, OFFSET variable2
MOVS

答案 3 :(得分:2)

是的,x86机器代码无法使用两个显式内存操作数(在[]中指定的任意地址)对一条指令进行编码

  

推荐的寄存器是什么

您无需保存/恢复的任何注册。

在所有主流的32位和64位调用约定中,EAX,ECX和EDX都是经过调用的,因此AL,CL和DL是不错的选择。在64位模式下,也可以找到SIL,DIL,r8b,r9b等,但是在机器代码中需要REX前缀,因此有较小的代码大小来避免它们。

出于性能原因,通常避免写AH,BH,CH或DH,除非您已阅读并理解以下链接,并且任何错误的依赖项或部分寄存器合并停顿都不会成为问题或根本不会发生在您的代码中。


  

(或者我应该改用堆栈)?

首先,您根本无法压入单个字节,因此无法从堆栈中进行字节加载/字节存储。对于单词,双字或qword(取决于CPU模式),您可以push [src] / pop [dst],但这比通过寄存器复制要慢得多。在从最终目的地读取数据之前,它引入了额外的存储/重载存储转发延迟,并且花费了更多的时间。

除非堆栈中的某个地方所需的目的地,并且您无法将该局部变量优化到寄存器中,在这种情况下,push [src]可以将其复制并分配堆栈足够的空间。

请参阅https://agner.org/optimize/中的the x86 tag wiki和其他x86性能链接

答案 4 :(得分:2)

从技术上讲,可以在内存之间移动。

尝试使用 MOVS (移动字符串),并设置 [E] SI [E] DI ,具体取决于是否 您要传输字节,单词等。

mov si, t_cur    ; Load SI with address of 't_cur'
mov di, t_last   ; Load DI with address of 't_last'
movsb            ; Move byte from [SI] to [DI]

; Some dummy data
t_cur    db 0x9a ; DB tells NASM that we want to declare a byte
t_last   db 0x7f ; (See above)

这比使用带有一个临时寄存器的普通加载+存储的效率低,但是它只用一条指令进行实际复制。

以下是 MOVS 的使用方式及其工作方式: https://www.felixcloutier.com/x86/movs:movsb:movsw:movsd:movsq

通常仅将rep前缀用于块副本,而不用于单个元素。 (现代CPU对于rep movsb具有相当有效的微代码,它使用AVX向量加载/存储指令接近循环速度。)

答案 5 :(得分:-2)

只想和你讨论“记忆障碍”。 在c代码

a = b;//Take data from b and puts it in a

将被汇总到

mov %eax, b # suppose %eax is used as the temp
mov a, %eax

系统无法保证分配的原子性。这就是我们需要人民币的原因 (阅读障碍)