首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >增加指针比做"mov [pointer+1],eax“快吗?

增加指针比做"mov [pointer+1],eax“快吗?
EN

Stack Overflow用户
提问于 2016-01-14 03:47:04
回答 1查看 1.4K关注 0票数 5

假设我们想在EDI存储一个字符串。这样储存会更快吗?

代码语言:javascript
复制
mov byte [edi],0
mov byte [edi+1],1
mov byte [edi+2],2
mov byte [edi+3],3
...

还是这边?

代码语言:javascript
复制
mov byte [edi],0
inc edi
mov byte [edi],1
inc edi
mov byte [edi],2
inc edi
mov byte [edi],3
inc edi
...

有些人可能会在“小结尾”中提出以下建议:

代码语言:javascript
复制
mov dword [edi],0x3210

或者大字号中的以下内容:

代码语言:javascript
复制
mov dword [edi],0x0123

但这不是我问题的重点。我的问题是,是增加指针的速度更快,然后mov就需要更多的指令,还是在每个mov指令中指定一个金额来增加EDI所指向的偏移地址?如果后者为真,那么在向偏移地址添加相同数目的多少个mov指令之后,是否值得将该数量添加到指针中?换句话说,这是

代码语言:javascript
复制
mov byte [edi+5],0xFF
mov byte [edi+5],0xFF
mov byte [edi+5],0xFF
mov byte [edi+5],0xFF

比这个还快?

代码语言:javascript
复制
add edi,5
mov byte [edi],0xFF
mov byte [edi],0xFF
mov byte [edi],0xFF
mov byte [edi],0xFF
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-14 04:38:23

有关如何优化http://agner.org/optimize/的文档,请参见x86 wiki中的其他链接。

这条路:

代码语言:javascript
复制
mov byte [edi],0
mov byte [edi+1],1
mov byte [edi+2],2
mov byte [edi+3],3
...

会更快。在任何当前的微体系结构AFAIK上使用位移没有额外的成本,除了额外的一个或四个字节的指令大小。在Intel SnB系列CPUs上,双寄存器寻址模式可能会慢一些。,但是固定的位移很好。

像gcc和clang这样的实际编译器在展开循环时总是使用第一种方法(有效地址中的位移)。

0x03020100的4字节存储几乎比四个单独的单字节存储快4倍。大多数现代CPU都有128 B数据路径,因此任何高达128 B的存储都会占用与8b存储相同的执行资源。AVX256b存储仍然比英特尔SnB / IvB上的两个128 B存储便宜(如果对齐的话),而Intel和以后的存储可以在一次操作中完成256 b存储。然而,mov-立即到内存只对8,16和32位操作数可用.mov r64, imm64 (仅注册)在64位模式下可用,但没有128或256个mov即时指令.

在32位模式下,只要有inc reg的一字节编码,inc edi / mov byte [edi],1就会有相同的代码大小,但在最近的英特尔和AMD微体系结构上仍然可以解码到两倍多的uop。如果代码仍然在存储吞吐量或其他方面遇到瓶颈,这可能不是一个问题,但是没有更好的方法。CPU非常复杂,通过计算uops来进行简单的分析并不总是与您在实践中得到的结果相匹配,但我认为每个商店之间的inc运行速度是非常不可能的。你能说的最好的是,它的运行速度可能不会太慢。它可能会使用更多的电力/热量,并且对超线程不太友好。

在64位模式下,inc rdx需要3个字节来编码:1个REX指定64位操作数大小(而不是默认的32位),1个操作码字节指定inc r/m,1个mod/rm字节指定rdx作为操作数。

所以在64位模式下,有一个代码大小的缺点。在这两种情况下,inc解决方案将在高价值的uop缓存中使用两倍多的条目( Intel SnB-系列CPU),其中包含融合域uop。

更多的uop也意味着在ROB中有更多的空间,所以无序的高管看不到前面那么远。

此外,一条inc指令链将延迟存储地址uop更早地计算多个存储地址(并将它们写入存储缓冲区)。英特尔冰湖有两个端口,可以运行存储地址uop(从3个在哈斯韦尔)。如果较早地准备好存储地址,则对以后的加载更好,因此CPU可以确保它们是独立的,或者它们确实重叠。它还能让它们更早地脱离调度器(RS),释放出无序的exec结构中的空间。

第二部分:

代码语言:javascript
复制
mov byte [edi+5],0xFF
mov byte [edi+5],0xFF
mov byte [edi+5],0xFF
mov byte [edi+5],0xFF

代码语言:javascript
复制
add edi,5            ; 3 bytes to encode.
mov byte [edi],0xFF  ; saving one byte in each instruction
mov byte [edi],0xFF
mov byte [edi],0xFF
mov byte [edi],0xFF

除非代码大小非常重要(不太可能),或者有更多的商店,否则使用第一种形式。第二种形式要长一个字节,但是融合域uop要少一个字节。它将在拥有uop缓存的CPU上占用更少的空间。在较旧的CPU(没有uop缓存)上,指令解码更像是一个瓶颈,因此在某些情况下,指令更好地排成4组是瓶颈。不过,如果你在商店的港口遇到瓶颈,情况就不会是这样了。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34781387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档