Re: @@@ A Serious Disassembly Question @@@
From: Sheldon Simms (sheldonsimms_at_yahoo.com)
Date: 11/16/03
- Next message: William: "Re: Programmer's unpaid overtime."
- Previous message: Joe \: "Re: Programming Language Productivity: The Stupidity of Programmers"
- In reply to: sugaray: "@@@ A Serious Disassembly Question @@@"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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.
- Next message: William: "Re: Programmer's unpaid overtime."
- Previous message: Joe \: "Re: Programming Language Productivity: The Stupidity of Programmers"
- In reply to: sugaray: "@@@ A Serious Disassembly Question @@@"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|