大会:移动两个存储器之间的地址
-
18-09-2019 - |
题
我努力学习会(所涵),我得到一个编译错误,在这一行:
mov byte [t_last], [t_cur]
错误是
error: invalid combination of opcode and operands
我怀疑,此错误的原因很简单,它不可能一章指令之间的移动两个地址,但半个多小时的搜索和我还没有能够确认这一点-是这样吗?
此外,假设我是对的,这意味着,我需要使用一个注册成为一个中间点用于复制的存储器:
mov cl, [t_cur]
mov [t_last], cl
什么建议的注册使用(或者我应该使用叠代替)?
解决方案
您的怀疑是正确的,你不能从内存中移动到内存中。
任何通用寄存器都行。记住推寄存器,如果你不知道里面是什么,并恢复回来一次。
其他提示
这是一个在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
注:推动和持久性有机污染物neceessary如果你需要保存寄存器的内容
。还有从存储器移动数据对存储器的MOVS命令:
MOV SI, OFFSET variable1
MOV DI, OFFSET variable2
MOVS
这在技术上是可以从存储器移动到存储器中。
尝试使用的 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向量加载/存储指令的环路的速度。)
这是正确的,x86机的代码不能进行编码指令有两个 明确 存储器操作数(任意指定的地址在 []
)
什么推荐的寄存器
任何注册,你不需要保存/恢复。
在所有主流的32位和64位叫公约,EAX,ECX,并EDX是呼破坏,使阿、CL,DL是很好的选择。一个字或字复制,通常想要一个 movzx
载入一个32位的注册,然后一个8位或16位的商店。这样可以避免虚假的依赖旧价值的登记册。只使用一个狭窄的16位或8位 mov
载荷如果你积极 想 合并入低比特的另一个价值。x86的 movzx
是模拟的说明等手臂 ldrb
.
movzx ecx, byte [rdi] ; load CL, zero-extending into RCX
mov [rdi+10], cl
在64位模式,SIL,DIL,r8b,r9b等也是好的选择,但需要一个雷克斯的前缀在机代码存储所有个小码尺寸的原因,以避免他们。
一般避免编写啊,BH,CH,或DH于性能的原因,除非你已阅读并理解以下链接和虚假的依赖关系或部分注册合并摊位不是一个问题或发生在所有的你的代码。
(或者我应该使用叠代替)?
首先,你不能推动一个字,所以没有办法你可以做一个字节载字节的储存从栈。用一个词,双字,或者四字(根据CPU模式),可以 push [src]
/ pop [dst]
, 但这是一个很大慢于复制通过注册。它引入了一个额外的储存/重新加载存储转发的延迟之前的数据可以从中读取的最终目的地,并需要更多的uops.
除非某个地方堆 是 所希望的目的地,你不能优化地方变成一个登记册,在这种情况下 push [src]
只是收到复制它存和分配堆空间。
看看 https://agner.org/optimize/ 和其他x86性能的链接 x86标签wiki
只是想讨论“记忆障碍”和你在一起。 在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
在系统不能保证分配的原子性。这就是为什么我们需要一个人民币 (读屏障)