Today, I accidentally saw a post about a small value, which reminds me of an attempt to reverse engineering a year ago. At that time, I used IDA for disassembly and saw a series of assembly code, which was very subtle, the final result is only to calculate the smaller values of two integers. But now I am trying very hard to remember how I did it.
I really wanted to reproduce the algorithm string, so I began to think about it myself. Let me talk about my scrutiny.
Proposition: Given integers x and y, calculate smaller values m.
The difference between the two numbers lies in their difference, so I thought of calculating z = x-y. Maybe I could use this median value and use some clever bitwise operations to find it, however, it seems difficult. So I plan to repeat the thought:
Possible situations: (temporarily ignore special cases z = 0)
1. x <y
Z <0
Is to find a function f that satisfies f (y, z) = x
2. x> y
Z> 0
This f must not only meet 1, but also f (y, z) = y at this time.
Because the algorithm aims to use addition and subtraction, bitwise operations, and perform calculations as simple as possible. So I chose addition.
Y + g (z) = x, z = x-y <0;
Y + g (z) = y, z = x-y> 0;
Eventually, it becomes a mona1 function.
Yes
G (z) = z, z <0
G (z) = 0, z> 0
That is, to find a one-dimensional piecewise function, and the operation is simple, so I thought of g (z) = (z> 31) & z
If z <0, z> 32 returns FFFFFFFF, and then returns the last z or z,
If z> 0, z> 32 returns 0000000, it is still 0.
So the final algorithm is
Z = x-y
M = (z> 31) & z) + y;
This algorithm should be close to what we saw at the beginning. It has obvious advantages that it is the most basic operation and does not contain control commands. It can be directly calculated by registers, with high efficiency.
The algorithm itself is not an amazing big algorithm, and it will certainly have its own optimization in the compiler. In fact, what I'm most pleased with is that this idea is very clear, I have been so happy to think about it for a long time. There are two main ideas: Classification and discussion, reducing the number of elements (reducing dual to one element ). This is also a very widely used method. The former mainly helps clarify ideas, while the latter mainly reduces complexity.
Updated:
Previously, z> 32 was used. A warning is displayed when gcc is used for compilation:
Right shift count> = width of type [enabled by default]
But I still don't know what kind of risks will exist, so I changed it to 31.