如何检查有符号整数是负数还是正数?
我是 x86 汇编语言的新手,我在寄存器 eax 中保存了一个有符号整数,我想检查该数字是负数还是正数。为此,我使用 bt
指令来检查第一位。
这是我所做的:
bt eax,0
jnc isNegative
bt
加载第一位进位标志,然后使用jnc
检查进位标志是0还是1。
如果是1,则应该是负数,并执行负指令... 但是,输出是不可预测的,有时我有一个正数,它会将其识别为负数。我做错了什么吗?
编辑:我刚刚意识到这可能与位编号有关。它实际上是检查最低有效位而不是第一位。让我尝试使用 bt eax, 31
I am new to x86 assembly language, I have a signed integer saved in register eax
, and I want to check if the number is negative or positive. To do that, I used bt
instruction to check the first bit.
Here is what I did:
bt eax,0
jnc isNegative
bt
loads the first bit to carry flag, and I used jnc
to check if carry flag is 0 or 1.
If it's 1, it should be a negative number, and does negative instructions...
however, the output is unpredictable, sometimes I have a positive and it recognize it as a negative number. Am I doing something wrong?
EDIT: I just realized it could have something to do with bit numbering. It is actually checking the least significant bit instead of the first bit. Let me try using bt eax, 31
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果设置了 MSB,则该值为负数。 FLAGS 中的 SF(符号标志)根据结果的该位进行设置。
或者从
test reg,reg
设置FLAGS的方式与cmp reg,0
相同,如果值为“less”,可以使用jl
跳转比零”。这是同样的事情。有趣的事实:这也可以作为优化无符号if(eax >= 0x80000000U)
的技巧。您可以使用效率较低的指令(更长,因为它必须包含 32 位常量)手动将其作为一位测试(不利用 SF)。这很像您的
bt eax,31
但在设置符号位时设置 ZF=0 而不是 CF=1。这适用于任何寄存器大小、字节 (int8_t)、字 (int16_t)、双字 (int32_t) 或 qword (int64_t)。例如,对于字节:
如果寄存器中的值是由“根据结果”设置 FLAGS 的内容生成的,就像大多数 ALU 指令一样,例如
添加ecx, edx
,无需测试即可通过
js
查看是否为负数ecx,ecx 首先。 SF 已通过add
指令根据 ECX 中值的 MSB 设置。术语:正数不包括零
x > 0 。 1 或更大的数字,不包括零。 (有时宽松地用作负数的反义词,但严格来说不是。)
x >= 0
。x < 0 。
因此,如果您想确定一个数字是正数还是负数,则需要进行两次单独的检查,除非您已经知道它非零。 (假设您使用积极的严格定义。有时,您可以从上下文推断某人表示一种条件,但精确的术语在计算中很有用,因此您最好自己使用。)
您的
bt
想法可以工作,但 x86 从底部的位 0(最低有效位)到位 31 进行编号,作为 32 位寄存器(如 EAX)的符号位。另外,CF 集表示负数,因此jc 负数
。但bt
并不更快,除非您确实希望进位标志中的条件与adc edx, 0
一起使用来执行negcount += (x<0)
计算负数什么的。另外,add eax,eax
或shl eax,1
会将 EAX 的最高位移入 CF(并且还会修改 EAX,与 BT 不同)。The value is negative if the MSB is set. The SF (sign flag) in FLAGS is set according to that bit of the result.
Alternatively since
test reg,reg
sets FLAGS the same way ascmp reg,0
, you could usejl
to jump if the value is "less than zero". That's the same thing. Fun fact: this also works as a trick for optimizing unsignedif(eax >= 0x80000000U)
.You can manually do it as a single-bit test (not taking advantage of SF) with a less efficient instruction (longer because it has to include the 32-bit constant.) This is a lot like your
bt eax,31
but setting ZF=0 instead of CF=1 when the sign bit is set.This works for any register size, byte (int8_t), word (int16_t), dword (int32_t), or qword (int64_t). For example with bytes:
If the value in a register was produced by something that sets FLAGS "according to the result", like most ALU instructions such as
add ecx, edx
, you canjs
to see if it's negative or not without needing totest ecx, ecx
first. SF is already set according to the MSB of the value in ECX, by theadd
instruction.Terminology: positive doesn't include zero
x > 0
. Numbers 1 or greater, not including zero. (Sometimes used loosely as the opposite of negative, but strictly speaking it's not.)x >= 0
.x < 0
.So if you want to find out if a number is positive or negative, that's two separate checks unless you already know it's non-zero. (Assuming you're using a strict definition of positive. Sometimes from context you can infer that someone means one condition, but precise terminology is useful in computing so prefer that yourself.)
Your
bt
idea could work, but x86 numbers bits from bit 0 at the bottom (least significant), to bit 31 as the sign-bit of a 32-bit register like EAX. Also, CF set means negative, sojc negative
. Butbt
isn't faster unless you actually want the condition in the carry flag for use withadc edx, 0
to donegcount += (x<0)
counting negative numbers or something. Alternatively,add eax,eax
orshl eax,1
will shift the top bit of EAX into CF (and also modify EAX, unlike BT).您可以使用
jge
和cmp
指令:You can use the
jge
andcmp
instructions:您当前的解决方案检查数字是偶数还是奇数,而是测试第 31 位:
或者您可以将数字与零进行比较,并测试它是否大于或等于它。
Your current solution checks if the number is even or odd, instead test the 31st bit:
Or you can compare the number to zero, and test whether it's greater than or equal to it.