Re: @@@ A Serious Disassembly Question @@@

From: Sheldon Simms (sheldonsimms_at_yahoo.com)
Date: 11/16/03


Date: Sun, 16 Nov 2003 14:37:10 -0500

On Sun, 16 Nov 2003 05:34:10 -0800, sugaray wrote:

> Hi folks, I wrote the following C code, and compiled using
> Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077

<code snipped for now, reappears later>

For now, here's my disassembly of the code, with your comments
stripped out.

> nB = dword ptr -8
> nA = dword ptr -4
>
> push ebp
> mov ebp, esp
> sub esp, 8
> mov [ebp+nA], 0

  a = 0;

> cmp [ebp+nA], 0
> jge short GE
> mov [ebp+nB], -5
> jmp short Handle

  if (a < 0)
    { b = -5; goto print_it; }

> GE:
> cmp [ebp+nA], 0
> jle short LE
> mov [ebp+nB], 5
> jmp short Handle

  if (a > 0)
    { b = 5; goto print_it; }

> LE:
> mov [ebp+nB], 0

  b = 0;

> Handle:
> mov eax, [ebp+nB]
> push eax
> push offset format
> call _printf
> add esp, 8

print_it:
  printf("%d\n",b);

> xor eax, eax
> mov esp, ebp
> pop ebp
> retn

  return 0;

Now all together that makes

  a = 0;
  if (a < 0)
    { b = -5; goto print_it; }
  if (a > 0)
    { b = 5; goto print_it; }
  b = 0;
print_it:
  printf("%d\n",b);
  return 0;

And your code is (supposedly):

> int main(void) {
> int a=0;
> int b;
>
> if(a<0) b=-5;
> else if(a>=0) b=5;
> else b=0;
>
> printf("%d\n",b);
>
> return 0;
> }

Since the logic of these two is different, either the Microsoft C
compiler can't compile simple code, or you typed in your main function
wrong. I choose to believe that you typed in your main function wrong.
Probably your main function actually contains this line:

> else if(a>0) b=5;

If that's the case, then the assembly code looks correct, although
not optimized at all.

> and after I rewrite the original C code in a more succinct way
> only in one line statement like this
>
> b=(a<0)?-5:((a>0)?5:0);
>
> then the disassembled code changed accordingly like this
>
> _main proc near
> nB = dword ptr -0Ch
> nTmp = dword ptr -8
> nA = dword ptr -4
>
> push ebp
> mov ebp, esp
> sub esp, 0Ch ; Set up stack frame
> mov [ebp+nA], 0 ; nA=0

  a = 0;

> cmp [ebp+nA], 0 ; compare nA with 0
> jge short GE ; if (nA >= 0) then goto GE
> mov [ebp+nB], -5 ; if (nA < 0) then nB=-5
> jmp short Handle

  if (a < 0)
    { b = -5; goto print_it; }

> GE:
> xor eax, eax ; IT'S KINDA TRICKY, ANY COMMENTS
> cmp [ebp+nA], 0 ; OBSERVATIONS WOULD BE WELCOME !!!!
> setle al ; if <= then AL=1
> dec eax ; EAX-- ;ESPECIALLY ON HOW AND WHY
> and eax, 5
> mov [ebp+nB], eax

This code translates to:

  if (a <= 0) b = 0;
  else b = 5;

Let's see why:

> GE:
> xor eax, eax ; IT'S KINDA TRICKY, ANY COMMENTS

  eax = 0x00000000;

> cmp [ebp+nA], 0 ; OBSERVATIONS WOULD BE WELCOME !!!!
> setle al ; if <= then AL=1

  if (a <= 0) eax = 0x00000001

Note this only happens if a == 0 since the case of a < 0 was already
handled above. Although the condition being checked is LE, I will
consider this to be a check for a == 0 from now on.

> dec eax ; EAX-- ;ESPECIALLY ON HOW AND WHY

  eax = eax - 1;

After this instruction, if a == 0 then

  new-eax == old-eax - 1 == 0x00000001 - 1 == 0x00000000

if a > 0 then

  new-eax == old-eax - 1 == 0x00000000 - 1 == 0xFFFFFFFF

So eax is now either 0x00000000 or 0xFFFFFFFF depending on what the
result of comparing a to 0 was. Abbreviated:

if a == 0: eax == 0x00000000
 if a > 0: eax == 0xFFFFFFFF

> and eax, 5

  eax = eax & 5;

if a == 0: eax == 0x00000000
 if a > 0: eax == 0x00000005

> mov [ebp+nB], eax

  b = eax

So this version of the code is equivalent:

  a = 0;
  if (a < 0)
    { b = -5; goto print_it; }
  if (a <= 0) b = 0;
  else b = 5;
print_it:
  printf("%d\n",b);
  return 0;

Which is correct.

> 2) was it any good, probably for the optimization purpose ?

The code is poorly optimzed. I suspect your compiler has some options
to improve the optimization level. You might want to investigate that.
Look at your code again:

int main(void) {
 int a=0;
 int b;
  
 if(a<0) b=-5;
 else if(a>=0) b=5;
 else b=0;
  
 printf("%d\n",b);
 
 return 0;
}

Notice that you are setting a to 0 and then testing the value of
a. The compiler should be able to notice that it is not possible
for the value of a to be anything but 0 and all of the testing
should be removed by the compiler. In other words, your program
is equivalent to:

int main (void) {
  printf("%d\n", 5);
  return 0;
}

As a comparison, here's what GCC produces for your program, when
compiled with medium-high (-O2) optimization:

.LC0:
        .string "%d\n"
        .text
.globl main
        .type main, @function
main:
        pushl %ebp
        movl %esp, %ebp
        subl $8, %esp
        andl $-16, %esp
        movl $5, 4(%esp) ; push 5
        movl $.LC0, (%esp) ; push "%d\n"
        call printf ; printf("%d\n",5);
        movl %ebp, %esp
        xorl %eax, %eax
        popl %ebp
        ret ; return 0

> 3) what kinda logic style would you prefer ?

Write your code so that it is readable to human beings. Don't
worry about what the compiler is doing.

> 4) if asked, how would you write this program in assembly ?

Like GCC did.



Relevant Pages

  • long(!) Re: need help on CFLAGS in /etc/make.conf please
    ... For example, MPlayer sets this high on purpose, so GCC will actually ... and the K&R compiler would've known exactly the kind of optimization we wanted. ... >> A msg from Richard Coleman, taken together with the GCC 3.x Known Bugs ...
    (freebsd-questions)
  • Re: gcc and 2.6 kernel
    ... *any* language GCC supports, except perhaps Fortran (I don't know ... > gotten right for each construct, is gotten right for the whole language ... whether or not optimization takes place. ... later stages so much that it speeds the compiler up, ...
    (comp.os.linux.development.system)
  • Re: data types
    ... Usually short is smaller than an int. ... Your compiler is either *really* old or broken or both. ... recommend either a version of gcc,, or Visual Studio ... Microsoft's Visual Studio Express has an onerous EULA). ...
    (comp.lang.c)
  • Re: data types
    ... Usually short is smaller than an int. ... memory per dms structure if they are 32-bit integers. ... current compiler system. ... recommend either a version of gcc,, or Visual Studio ...
    (comp.lang.c)
  • Re: Behavior of the code
    ... What is surprising is that the gcc printf recognizes somehow hh, ... The GNU compiler collection contains a "C compiler" ... uses whatever libraries are provided by the underlying system. ... The main body of optimization is either part of the ...
    (comp.lang.c)