0

Disassembling the following function using VS2010

int __stdcall modulo(int a, int b)
{
    return a % b;
}

gives you:

push        ebp  
mov         ebp,esp  
mov         eax,dword ptr [ebp+8]  
cdq  
idiv        eax,dword ptr [ebp+0Ch]  
mov         eax,edx  
pop         ebp  
ret         8  

which is pretty straightforward.

Now, trying the same assembly code as inline assembly fails with error C2414: illegal number of operands, pointing to idiv.

I read Intel's manual and it says that idiv accept only 1 operand:

Divides the (signed) value in the AX, DX:AX, or EDX:EAX (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers

and sure enough, removing the extra eax compiles and the function returns the correct result.

So, what is going on here? why is VS2010 emitting erroneous code ? (btw, VS2012 emits exactly the same assembly)

Yuval
  • 907
  • 9
  • 24
  • Did you generate assembly output (by the compiler) or did you disassemble a compiled binary? – xxbbcc May 14 '14 at 21:03
  • What assembler are you using? – Fred Larson May 14 '14 at 21:04
  • @FredLarson I assume he's using the assembler that comes with VS 2010 (ml.exe). – xxbbcc May 14 '14 at 21:05
  • I am using the disassembly feature from within the IDE – Yuval May 14 '14 at 21:06
  • @xxbbcc: You can assume that, but it may not be the case. If the generated assembly code is from VS2010, I would expect its assembler to be able to handle the format. – Fred Larson May 14 '14 at 21:06
  • 1
    @Yuval See this http://stackoverflow.com/questions/1020498/how-to-view-the-assembly-behind-the-code-using-visual-c and generate assembly out when you compile. – xxbbcc May 14 '14 at 21:10
  • @FredLarson you would hope so, but you will often be disappointed. – nobody May 14 '14 at 21:12
  • @AndrewMedico: Yes, especially since it's copied out of the IDE disassembly window as opposed to being a generated .asm file. That could be a whole different ball game. – Fred Larson May 14 '14 at 21:14
  • @xxbbcc I followed your suggestion and indeed, the idiv statement was correctly emitted. Now the question is, why is there any difference? – Yuval May 14 '14 at 21:21
  • @Yuval I'm not sure. It could be a bug or it could be intentional. I personally never expected the disassembly output to be correct assembly (can't explain why). You should post this as a bug to Microsoft and see what response you get. (My bet is "Won't fix".) – xxbbcc May 14 '14 at 22:02
  • @Yuval As a general rule, I'd never fully trust anything decompiled, that's why I suggested to use the compiler's assembly output. – xxbbcc May 14 '14 at 22:04
  • @xxbbcc did you mean decompiled or disassembled? Any way, thanks for taking the time to answer! – Yuval May 14 '14 at 22:21
  • @Yuval I meant decompiled and / or disassembled code. When it comes to syntax, only the compiler's output is reliable (and even that could be buggy, just not very likely). – xxbbcc May 14 '14 at 22:25

1 Answers1

1

The difference, most likely, is that the author of the disassembler intended for its output to be read by a human rather than by an assembler. Since it's a disassembly, one assumes the underlying code has already been assembled/compiled, so why worry about whether it can be re-assembled?

There are two major possibilities here:

  • The author didn't realize or didn't remember that the dividend is implicit for idiv (in which case this could be considered a bug).
  • They felt that making it explicit in the output would be helpful for a reader trying to understand the flow of the disassembly (in which case it's a feature). Without the explicit operand, it would be easy to overlook that idiv both depends on and modifies eax when scanning the disassembly.
Russell Borogove
  • 18,516
  • 4
  • 43
  • 50