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
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,regsets FLAGS the same way ascmp reg,0, you could usejlto 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,31but 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 canjsto see if it’s negative or not without needing totest ecx, ecxfirst. SF is already set according to the MSB of the value in ECX, by theaddinstruction.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
btidea 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. Butbtisn’t faster unless you actually want the condition in the carry flag for use withadc edx, 0to donegcount += (x<0)counting negative numbers or something. Alternatively,add eax,eaxorshl eax,1will shift the top bit of EAX into CF (and also modify EAX, unlike BT).