- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
单个 x86 指令能否在“0”和“1”之间切换 bool 值?
我想到了以下方法,但都导致了两 strip 有 gcc 的 -O3 标志的指令。
status =! status;
status = 1 - status;
status = status == 0 ? 1: 0;
int flip[2] = {1, 0};
status = flip[status];
有没有更快的方法来做到这一点?
这是我试过的:https://godbolt.org/g/A3qNUw
我需要的是一个切换输入和返回的函数,以编译为一条指令的方式编写。类似于此功能的内容:
int addOne(int n) { return n+1; }
lea eax, [rdi+1] # return n+1 in a single instruction
ret
最佳答案
要翻转整数位,请使用 xor
像这样:foo ^= 1
.
gcc 已经知道 bool
的优化,所以你可以 return !status;
像正常人一样不损失任何效率。 gcc 编译 status ^= 1
异或指令也是如此。事实上,除了表查找之外,你所有的想法都会编译成一个 xor
。指令 bool
输入/返回值。
检查一下 on the Godbolt compiler explorer与 gcc -O3
, 带有 bool
的 asm 输出面板和 int
.
MYTYPE func4(MYTYPE status) {
status ^=1;
return status;
}
# same code for bool or int
mov eax, edi
xor eax, 1
ret
对比
MYTYPE func1(MYTYPE status) {
status = !status;
return status;
}
# with -DMYTYPE=bool
mov eax, edi
xor eax, 1
ret
# with int
xor eax, eax
test edi, edi
sete al
ret
半相关:XOR是add-without-carry。所以如果你只关心低位,你可以用 lea eax, [rdi+1]
复制并翻转低位.参见 Check if a number is even 与 and eax, 1
结合使用时很有用只需 2 条指令即可完成。
bool
不同于int
? The x86-64 System V ABI要求调用者传递 bool
传递 0 或 1 值,而不仅仅是任何非零整数。因此,编译器可以假设输入。
但是用int foo
, C 表达式 !foo
需要对值进行“ bool 化”。 !foo
类型为 _Bool
/(又名 bool
如果你 #include <stdbool.h>
),并将其转换回整数必须产生 0 或 1 的值。如果编译器不知道 foo
必须是 0
或 1
, 它无法优化 !foo
至 foo^=1
,并且无法意识到 foo ^= 1
在 truthy/falsy 之间翻转一个值。 (在某种意义上,if(foo)
在 C 语言中表示 if(foo != 0)
)。
这就是为什么您得到 test/setcc(在 int
之前由 xor
-zeroing a register 零扩展为 32 位 test
)。
相关:Boolean values as 8 bit in compilers. Are operations on them inefficient? .像 (bool1 && bool2) ? x : y
这样的东西并不总是像您希望的那样高效地编译。编译器非常好,但确实存在优化错误。
mov
呢?指令?它会在内联时消失,如果编译器不需要/不想保留旧的未翻转值供以后使用。但是在独立函数中,第一个 arg 在 edi
中,返回值需要在eax
中(在 x86-64 System V 调用约定中)。
像这样的微型函数非常接近作为大型函数的一部分可能得到的函数(如果不能将此翻转优化为其他函数),但需要将结果保存在不同的寄存器中是一个混杂因素。
x86 没有复制和异或整数指令,因此对于独立函数,它至少需要 mov
。从 arg 传递寄存器复制到 eax
.
lea
是特殊的:它是为数不多的整数 ALU 指令之一,可以将结果写入不同的寄存器而不是破坏其输入。 lea
是 copy-and-shift/add instruction ,但 x86 中没有复制和异或指令。许多 RISC 指令集有 3 个操作数指令,例如 MIPS 可以做 xor $t1, $t2, $t3
.
AVX 引入了 vector 指令的非破坏性版本(在大量代码中节省了大量 movdqa
/movups
寄存器复制),但对于整数,只有少数新指令可以做不同的事情。 rorx eax, ecx, 16
例如 eax = rotate_right(ecx, 16)
,并使用与非破坏性 AVX 指令相同的 VEX 编码。
关于c++ - 可以在单个 CPU 指令中在 0 和 1 之间翻转位/整数/ bool 值的任何可能代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49056128/
我有一个数据集,我试图在其中探索将变量限制在给定值并将超出的部分滚动到后续间隔的影响。我可以从概念上看到一些方法可以使用 cumsum() 来做到这一点。或类似的,但正在努力了解如何以合乎逻辑的方式实
我正在开发一个使用 iPhone 前置摄像头的应用程序。当使用该相机拍摄图像时,iPhone 会水平扭曲图像。我想将其镜像回来,以便能够保存它并按照在 iPhone 屏幕上看到的方式显示它。 我读了很
这是 HTML // stuff here Order /
我正在使用 Jquery - 是否有一种简单的方法可以在用户滑过 div 时更改它的背景颜色? 最佳答案 你可以用 CSS 做到这一点: #myDiv:hover { background-color
有谁知道是否可以翻转图像并在其背面显示内容。这就是我的意思:想象一下你手里拿着一张肖像。然后你翻转并查看肖像的背面,背面有文字。我正在寻找类似的东西,单击图像将镜像/翻转到另一侧,上面有文字。不可90
我在翻车方面遇到了一些麻烦..希望你能帮助我! 我正在使用 li 导航,我希望有单独的框链接到不同的页面。这部分很好,可以正常工作。我希望能够将鼠标悬停在框上并让框和链接改变颜色。我可以毫无问题地改变
所以我目前在 Vuejs 中有一个组件,用户可以在其中从他们的本地文件系统中选择一个文件。用户选择图片后,图片会在 div 中预览 codesandbox .出于某种原因,某些图像会自动“翻转”到侧面
我有一个滚动顶部菜单。我正在尝试获取它,以便我的背景图像 (17px x 13px) 悬停在中央。我已经尝试了所有背景 css 属性,但似乎没有任何效果。我是不是用错了方法? 这是我的 CSS: #n
我以前用过这个效果,一切正常(据我所知),但就是不行。我错过了什么? Fiddle here Sprite here 谢谢。 最佳答案 由于您的 Sprite 是水平排列的,因此您需要像这样偏移悬停状
代码后面的代码不起作用,因为重新查找接受字符串作为第一个参数,正则表达式作为第二个参数。 (-> "hello" .toUpperCase (re-find #".$")) 如果我像这
我想使用 CABasicAnimation 翻转 UILabel。动画将永远重复,并将在两个不同值之间更改 UILabel 的文本。 - (void)animateLabel { [self
旋转 WPF 图像非常简单 imgCurrent.LayoutTransform = new RotateTransform(_rotationAngle); 水平和垂直镜像呢? 机外: In GDI
我需要创建一个动画 - 翻转一个 View 并显示另一个。 当前显示的 View 的宽度慢慢减小到零,之后要显示的 View 的宽度必须从零开始增加。 在此期间,高度从当前显示的高度变为略微降低的高度
我正在尝试找到翻转 Rust 中 boolean 值的最快方法?即 false => true true => false 对于我的应用程序,我不关心 boolean 值的当前值,只关心它被翻转了。对
是否可以翻转 primefaces 中的数据表,以使标题位于左侧而不是顶部?我有下表: 如您所见
我在翻转 View 时遇到了一些问题。我的 View Controller 中有以下代码: - (void)loadFlipsideViewController { ProblemViewFl
我正在使用翻转动画在 View Controller 中的两个 View 之间制作动画。问题是动画发生时背景显示白色空白背景。我想显示黑色背景。 我尝试在 IB 和代码中将主视图的背景颜色设置为黑色。
请考虑下面的代码,并告诉我我做错了什么。 我想在两个 UIView 之间切换。 不知何故,当我从初始 View 翻转时,我只是得到翻转的 View ,没有动画。当我向后翻转时,动画显示得很好。 翻转是
我有一个 NSScrollView,需要在其中显示可变数量的 NSView。我制作了一个自定义 NSView,它的 isFlipped 返回 YES 并将我的 NSView 放入其中,然后将其设置为
我有一个 NSView 的子类,它重新实现了许多鼠标事件函数。例如,在 mouseDown 中从我使用的 NSEvent 获取点: NSEvent *theEvent; // <- argument
我是一名优秀的程序员,十分优秀!