#1
|
|||
|
|||
Arithmetic coerce to negative one, and the like
See below, this was a simple late night mistake.
Just an interesting asm question, since we know that: mul [val], -1 is inefficient in terms of clock cycles, is there a pure Boolean algebra (and/or/xor/not/neg) way of doing this without doing expensive multiplication? Last edited by chants; 01-19-2017 at 08:48. |
#2
|
|||
|
|||
You can move the value to a register and use NEG on it (assuming x86, 32 bit):
Code:
mov eax, [val] neg eax mov [val], eax Code:
xor exc, ecx mov eax, [val] sub ecx, eax mov [val], ecx |
The Following User Says Thank You to mcp For This Useful Post: | ||
chants (01-19-2017) |
#3
|
|||
|
|||
It is a bit early in the morning :-D
What I really meant to ask, was can we take an expression that is 0 or non-zero and convert it to 0 or -1. Either an all-0 or all-1 bitmask. 0->0 non-zero->-1 With pure arithmetic and no conditional statements. With conditional statements, there are many ways and all are easy. But without, its not as simple. I noticed that (A OR -A) = 0 for 0, but turns the high bit on except for the sign bit power of 2 value e.g. 0x80000000. Perhaps using CDQ. Code:
mov eax, [val] mov edx, eax neg edx or eax, edx cdq mov eax, edx The only other interesting property like this I could think of is <0 -> -1, 0 -> 0, >1 ->1 which also would be about as tricky without conditionals and purely arithmetically. Actually you do something along the lines of multiply the output of previous code by the carry flag after subtracting from 0(sub, adc, mul) and I don't think you can avoid the mul. Any thoughts |
The Following User Says Thank You to chants For This Useful Post: | ||
niculaita (02-08-2017) |
#4
|
||||
|
||||
Using modern compiler optimizations it suggests that doing something like this:
Code:
int32_t val1 = 1234; int32_t val2 = -val1; Code:
mov [ebp+var_4], 4D2h mov eax, [ebp+var_4] neg eax mov [ebp+var_4], eax Code:
int32_t val1 = 1234; val1 *= -1; |
#5
|
|||
|
|||
IIUC, you want to express something like this in assembly:
Code:
int result = n ? -1 : 0; Code:
mov eax, [val] neg eax sbb eax, eax Example: eax contains a non-zero value, say x. neg eax turns this into -x and sets the CF. sbb eax, eax computes eax = eax - eax - cf <-> eax = 0 - CF. Same drill when eax is zero initially. |
#6
|
|||
|
|||
Yes, that was the pearl of wisdom needed here. I had long forgotten this old SBB trick. From a C perspective its the casting to bool operation.
It would be nice if all the assembler bit tricks were compiled somewhere as similar to: https://graphics.stanford.edu/~seander/bithacks.html |
#7
|
|||
|
|||
I think you may also take advantage of the instruction "setnz":
Code:
mov eax, [val] or eax, eax setnz al neg al movsx eax, al |
The Following User Says Thank You to BlackWhite For This Useful Post: | ||
niculaita (02-08-2017) |
#8
|
|||
|
|||
@BlackWhite Why would you? It's more code and it's less efficient. Clearly, there is an infinite amount of additional ways to express this, but there is no advantage in doing so!?
|
#9
|
|||
|
|||
Yes, setnz is not as efficient as sbb;
yet, it provides a variant way for the job. Since sbb is forgotten by someone, setnz & movsx may also be the case. |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Hex-Rays and negative structure offsets | jonwil | General Discussion | 3 | 02-20-2019 10:37 |