- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
据我了解,cmp指令将设置标志寄存器中的某些位。然后,您可以使用诸如jle,jnp等指令来基于这些指令进行分支。
我想知道的是如何从比较中恢复整数值。
示例:以下是有效的c语法
y = x[a >= 13];
最佳答案
基本上可以通过三种方式完成此操作。我一次要遍历他们。
一种解决方法基本上就是您在问题中描述的内容:进行比较,然后跳转到分别实现这两种可能性的代码。例如:
cmp [a], 13 ; compare 'a' to 13, setting flags like subtraction
jge GreaterThanOrEqual ; jump if 'a' >= 13, otherwise fall through
mov eax, [x * 0 * sizeof(x[0])] ; EAX = x[0]
jmp Next ; EAX now loaded with value, so do unconditional jump
GreaterThanOrEqual:
mov eax, [x * 1 * sizeof(x[0])] ; EAX = x[1]
; EAX now loaded with value; fall through
Next:
mov [y], eax ; store value of EAX in 'y'
x[1]
的指令,或者跳转到读取/加载
x[0]
的指令。然后,它移至将值存储到
y
的指令。
(a >= 13) ? 1 : 0
(a >= 13) ? 125 : -8
SETcc
指令。
cc
部分代表“条件代码”,并且所有条件代码都与条件跳转指令的条件代码相同。 (实际上,您可以将所有条件跳转指令写为
Jcc
。)例如,
jge
表示“如果大于等于则跳转”。类似地,
setge
表示“如果大于等于则设置”。简单。
SETcc
的技巧是设置一个BYTE大小的寄存器,这基本上意味着
AL
,
CL
,
DL
或
BL
(还有更多选项;您可以设置其中一个的高字节这些寄存器,和/或在64位长模式下,还有更多选项,但这是操作数的基本选择)。
xor edx, edx ; clear EDX
cmp [a], 13 ; compare 'a' to 13, setting flags like subtraction
setge dl ; set DL to 1 if greater-than-or-equal, or 0 otherwise
mov eax, [x * edx * sizeof(x[0])]
mov [y], eax
DL
中,然后用作加载的一部分(
MOV
指令)。
DL
是完整的32位
EDX
寄存器的低字节。这就是为什么我们需要预先清除完整的
EDX
的原因,因为
setge dl
仅影响低字节,但是我们希望完整的
EDX
为0或1。事实证明,将全部寄存器预清零是
the most optimal way of doing this on all processors,但是还有其他方法,例如在
MOVZX
指令后使用
SETcc
。链接的答案对此进行了详细介绍,因此在这里我不会感到惊讶。关键在于
SETcc
仅设置寄存器的低字节,但是后续指令要求整个32位寄存器具有该值,因此您需要消除高字节中的垃圾。
y = x[a >= 13]
之类的代码时,编译器将生成99%的代码。
SETcc
指令为您提供了一种方法,可以根据一个或多个标志的状态来设置字节,就像可以在标志上进行分支一样。基本上,这就是您正在考虑的一条允许直接访问标志的指令。
(a >= 13) ? 1 : 0
(a >= 13) ? 125 : -8
SETcc
指令,但是之后要花一些点花哨的时间来“固定”结果0或1为您想要的值。例如:
xor edx, edx
cmp [a], 13
setge dl
dec edx
and dl, 123
add edx, 125
; do whatever with EDX
CMOVcc
,其中
cc
再次引用“条件代码”,与前面示例中的完全一样。
CMOVcc
指令是在1995年左右的Pentium Pro中引入的,此后一直在所有处理器中使用(不是Pentium MMX,而是Pentium II和更高版本),因此基本上就是您今天所见的一切。
xor edx, edx ; EDX = 0
mov eax, 1 ; EAX = 1
cmp [a], 13 ; compare 'a' to 13 and set flags
cmovge edx, eax ; EDX = (a >= 13 ? EAX : EDX)
mov eax, [x * edx * sizeof(x[0])]
mov [y], eax
EAX
移到
EDX
是有条件的-仅在标志指示条件
ge
(大于或等于)时才会发生。因此,它可以执行基本的C三进制运算,如指令右侧的注释所述。如果标志指示
ge
,则将
EAX
移入
EDX
。否则,什么都不会移动,并且
EDX
保持其原始值。
CMOV
指令而不是
SET
指令,但这与我们先前在
SETGE
中看到的以前的实现没有任何优势。实际上,这确实不是最佳选择。
CMOV
真正有用的地方是,您可以消除获取除旧的0或1以外的值所需的位旋转代码。例如:
mov edx, -8 ; EDX = -8
mov eax, 125 ; EAX = 125
cmp [a], 13 ; compare 'a' to 13 and set flags
cmovge edx, eax ; EDX = (a >= 13 ? EAX : EDX)
; do whatever with EDX
EDX
寄存器,而不是将其设置为0或1,然后不得不将其操纵为所需的值。因此,编译器将使用
CMOV
指令(当针对支持它们的处理器时,如上所述)实现更复杂的逻辑,例如
(a >= 13) ? 125 : -8
int Foo(int a)
{
return a >= 13;
}
bool
也可以在这里工作。当然,如果使用条件运算符返回0或1以外的值,则需要返回
int
。
gcc -S -masm=intel MyFile.c
-S
为输入源代码文件生成一个程序集列表,而
-masm=intel
将程序集列表语法格式切换为Intel样式。
CMOV
指令。最右边的窗格显示了GCC 7.1的汇编输出,用于不支持
CMOV
指令的非常旧的处理器。酷吧?您可以轻松地操纵编译器开关,并观察输出如何变化。例如,如果您使用
-m64
(64位)而不是
-m32
(32位),则会看到参数是通过寄存器(
EDI
)传递的,而不是通过堆栈,并且必须作为函数中的第一条指令加载到寄存器中。
关于x86 - 获取比较指令的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45180785/
我的问题:非常具体。我正在尝试想出解析以下文本的最简单方法: ^^domain=domain_value^^version=version_value^^account_type=account_ty
好吧,这就是我的困境: 我正在为 Reddit 子版 block 开发常见问题解答机器人。我在 bool 逻辑方面遇到了麻烦,需要一双更有经验的眼睛(这是我在 Python 中的第一次冒险)。现在,该
它首先遍历所有 y 值,然后遍历所有 x 值。我需要 X 和 y 同时改变。 For x = 3 To lr + 1 For y = 2 To lr anyl.Cells(x, 1)
假设我有一个包含 2 列的 Excel 表格:单元格 A1 到 A10 中的日期和 B1 到 B10 中的值。 我想对五月日期的所有值求和。我有3种可能性: {=SUM((MONTH(A1:A10)=
如何转换 Z-score来自 Z-distribution (standard normal distribution, Gaussian distribution)到 p-value ?我还没有找到
我正在重写一些 Javascript 代码以在 Excel VBA 中工作。由于在这个网站上搜索,我已经设法翻译了几乎所有的 Javascript 代码!但是,有些代码我无法准确理解它在做什么。这是一
我遇到过包含日期格式的时间戳日期的情况。然后我想构建一个图表,显示“点击”项目的数量“每天”, //array declaration $array1 = array("Date" => 0); $a
我是scala的新手! 我的问题是,是否有包含成员的案例类 myItem:Option[String] 当我构造类时,我需要将字符串内容包装在: Option("some string") 要么 So
我正在用 PHP 创建一个登录系统。我需要用户使用他或她的用户名或电子邮件或电话号码登录然后使用密码。因为我知道在 Java 中我们会像 email==user^ username == user 这
我在 C++ 项目上使用 sqlite,但是当我在具有文本值的列上使用 WHERE 时出现问题 我创建了一个 sqlite 数据库: CREATE TABLE User( id INTEGER
当构造函数是显式时,它不用于隐式转换。在给定的代码片段中,构造函数被标记为 explicit。那为什么在 foo obj1(10.25); 情况下它可以工作,而在 foo obj2=10.25; 情况
我知道这是一个主观问题,所以如果需要关闭它,我深表歉意,但我觉得它经常出现,让我想知道是否普遍偏爱一种形式而不是另一种形式。 显然,最好的答案是“重构代码,这样你就不需要测试是否存在错误”,但有时没有
这两个 jQuery 选择器有什么区别? 以下是来自 w3schools.com 的定义: [attribute~=value] 选择器选择带有特定属性,其值包含特定字符串。 [attribute*=
为什么我们需要CSS [attribute|=value] Selector根本当 CSS3 [attribute*=value] Selector基本上完成相同的事情,浏览器兼容性几乎相似?是否存在
我正在解决 regx 问题。我已经有一个像这样的 regx [0-9]*([.][0-9]{2})。这是 amont 格式验证。现在,通过此验证,我想包括不应提供 0 金额。比如 10 是有效的,但
我正在研究计算机科学 A 考试的样题,但无法弄清楚为什么以下问题的正确答案是正确的。 考虑以下方法。 public static void mystery(List nums) { for (
好的,我正在编写一个 Perl 程序,它有一个我收集的值的哈希值(完全在一个完全独立的程序中)并提供给这个 Perl 脚本。这个散列是 (string,string) 的散列。 我想通过 3 种方式对
我有一个表数据如下,来自不同的表。仅当第三列具有值“债务”并且第一列(日期)具有最大值时,我才想从第四列中获取最大值。最终值基于 MAX(DATE) 而不是 MAX(PRICE)。所以用简单的语言来说
我有一个奇怪的情况,只有错误状态保存到数据库中。当“状态”应该为 true 时,我的查询仍然执行 false。 我有具有此功能的 Controller public function change_a
我有一个交易表(针对所需列进行了简化): id client_id value 1 1 200 2 2 150 3 1
我是一名优秀的程序员,十分优秀!