- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下代码:
char swap(char reg, char* mem) {
std::swap(reg, *mem);
return reg;
}
我希望这可以编译为:
swap(char, char*):
xchg dil, byte ptr [rsi]
mov al, dil
ret
但是它实际编译的是(在
-O3 -march=haswell -std=c++20
处):
swap(char, char*):
mov al, byte ptr [rsi]
mov byte ptr [rsi], dil
ret
参见
here for a live demo。
xchg
的文档中,第一种形式应该完全可行:
XCHG - Exchange Register/Memory with Register
Exchanges the contents of the destination (first) and source (second) operands. The operands can be two general-purpose registers or a register and a memory location.
xchg
?我也尝试过其他示例,例如交换指针,交换三个操作数,交换
char
以外的其他类型,但我在编译输出中从未得到
xchg
。怎么来的?
最佳答案
TL:DR:因为编译器针对速度进行了优化,而不是针对听起来相似的名称进行了优化。他们也可以采用其他许多可怕的方法来实现它,但选择不这样做。
带有mem的 xchg具有隐式lock
前缀(在386及更高版本上),因此的速度非常慢。除非您需要原子交换,否则总是希望避免它,或者在您确实希望结果与原始值位于同一寄存器的情况下,完全不考虑代码大小而对性能进行了优化。有时在幼稚(性能不佳)手写的Bubble中看到,作为交换2个内存位置的一部分。clang -Oz
可能会发疯,IDK,但希望在这种情况下不会,因为您的xchg方式的代码更大,两个指令都需要REX前缀才能访问DIL,而2-mov方式则是2字节和3字节指令。 clang -Oz
确实做了诸如push 1
/ pop rax
的工作,而不是mov eax, 1
来节省2个字节的代码大小。
对于不需要是原子的交换,GCC -Os
不会使用xchg
,因为-Os
仍然在乎速度。
另外,IDK为什么会认为xchg +依赖mov比两个可以并行运行的独立mov
指令更快或更更好的选择。 (不管哪个uop首先发现其执行端口空闲,存储缓冲区都确保在加载后正确排序存储。)
查看https://agner.org/optimize/和https://stackoverflow.com/tags/x86/info中的其他链接
认真地说,我只是没有看到任何可能的原因,为什么您会认为编译器可能想要使用xchg
,尤其是考虑到调用约定未在RAX中传递arg,因此您仍然需要2条指令。即使对于寄存器,英特尔CPU上的xchg reg,reg
也只有3微码,它们是微码微码,无法从消除运动中受益。 (某些AMD CPU具有2-uop xchg reg,reg
。Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures?)
我也猜你在看clang输出。通过使用movzx eax, byte ptr [rsi]
加载GCC will avoid partial register shenanigans (like false dependencies),即使返回值只是低字节。零扩展负载要比合并RAX的旧值便宜。因此,这是xchg
的另一个缺点。
关于c++ - 为什么clang和GCC不使用xchg来实现std::swap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63706623/
有人可以解释一下 xchg 在这段代码中是如何工作的吗?鉴于 arrayD 是一个 1,2,3 的 DWORD 数组。 mov eax, arrayD ; eax=1 xchg eax, [array
维基百科提供的使用 x86 XCHG 命令的自旋锁的示例实现是: ; Intel syntax locked: ; The lock variable. 1
我已经看过 this answer和 this answer ,但对于 mfence 的等价或不等价,两者似乎都没有明确和明确的说明。和 xchg在没有非时间指令的假设下。 英特尔 instructi
我在学校上汇编类(class),他们问了这个问题: 接下来的非法操作有哪些: 1. mov bh,al 2. mov dh,cx 3. mov bh,bh 4. m
我有一套并测试基于 xchg 的程序集锁。我的问题是: 在使用xchg 指令时是否需要使用内存防护(mfence、sfence 或lfence)? 编辑: 64 位平台:使用 Intel nehale
在 msdn 上 http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208(v=vs.85).aspx , MemoryBarr
我想在 C++ 中以原子方式实现 TestandSet。 c++中的xchg指令相当于什么操作 最佳答案 您可以使用内部函数,具体取决于您的编译器。例如在 gcc 中使用 __sync_lock_te
我假设简单的自旋锁不会进入操作系统等待这个问题的目的。 我看到简单的自旋锁通常使用 lock xchg 来实现。或 lock bts而不是 lock cmpxchg . 但不是cmpxchg如果期望不
我正在查看程序的反汇编(因为它崩溃了),并注意到很多 xchg ax, ax 我用 google 搜索了一下,发现它本质上是一个 nop,但为什么 Visual Studio 会执行 xchg
如果 mem 是共享内存位置,我是否需要: XCHG EAX,mem 或者: LOCK XCHG EAX,mem 以原子方式进行交换? 谷歌搜索会得到"is"和“否”的答案。有谁明确知道这一点吗? 最
最近我接触到了汇编语言。 x86 程序集有 an xchg instruction交换两个寄存器的内容。 由于每个 C 代码都首先转换为汇编代码,因此如果像头文件 stdio.h 中那样在 C 中内置
我是一名优秀的程序员,十分优秀!