通过逆向工程从x86汇编还原C语言mystery函数
mystery and mystery_util x86 Assembly Functions Alright, let's dig into this x86 assembly code to figure out what these functions do. We'll start with the complete mystery_util helper function first, since its full assembly is provided, then touch on the partial mystery code you shared.
Breaking Down mystery_util (Signature: int mystery_util(int n))
In x86-64 System V ABI (the common calling convention for Linux/macOS), the first integer argument is passed in %edi, and the return value is stored in %eax. Let's walk through each instruction:
400526: mov %edi,%eax:Copy the input parametern(from%edi) into%eax—this sets up our return value register with the raw input first.400528: shr %eax:Perform a logical right shift on%eaxby 1 bit. For non-negative integers, this is exactly equivalent to dividing by 2 and discarding the remainder. For negative integers, note that logical shift zero-fills the top bit, which will flip the sign to positive (unlike arithmetic shiftsar, which preserves the sign bit).40052a: and $0x1,%edi:Do a bitwise AND ofnwith0x1to isolate the least significant bit. This gives us1ifnis odd,0ifnis even.40052d: add %edi,%eax:Add that 0/1 result to our shifted value in%eax.40052f: c3 retq:Return the final value in%eaxto the caller.
What does mystery_util actually compute?
For non-negative integers (the likely intended use case here), this function calculates the ceiling of n divided by 2, or equivalently (n + 1) // 2 using integer division:
- If
nis even:n/2 + 0 = n/2(which matches(n+1)//2since even n +1 divided by 2 still truncates to n/2) - If
nis odd:(n//2) + 1 = (n+1)//2
Test it with examples:
mystery_util(4)→4 >> 1 + 0 = 2 + 0 = 2mystery_util(5)→5 >> 1 + 1 = 2 + 1 = 3mystery_util(0)→0 + 0 = 0
For negative inputs, the behavior is quirky (e.g., mystery_util(-3) would return 2147483647 for 32-bit ints) because of the logical shift, but that's probably not the intended use case here.
Partial Look at mystery (Signature: int mystery(int n))
The mystery function starts with two instructions, but the second one is truncated:
400530: mov %edi,%eax:Copy the inputninto%eax, just likemystery_utildoes initially.400532: 8d 3c fd 00 0...:The opcode8dtells us this is anlea(load effective address) instruction. The full instruction would look something likelea 0x00000000(,%edi,4),%edi(scalingnby 4) or a similar memory calculation, but we can't fully reverse-engineermysterywithout the complete assembly for this line and the rest of the function.
内容的提问来源于stack exchange,提问作者minturtle

