Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assembly Compared With C code

Tags:

c

x86

assembly

att

I am currently learning assembly and C programming languages and I have a couple of questions about it.

C code

int arith(int x, int y, int z) {
    int t1 = x + y;
    int t2 = z*48;
    int t3 = t1 & 0xFFFF;
    int t4 = t2 * t3;
    return t4;
}

Assembly code

movl  16(%ebp),%eax         z
leal  (%eax,%eax,2), %eax   z*3
sall  $4,%eax               t2 = z*48
movl  12(%ebp),%edx         y
addl  8(%ebp),%edx          t1 = x+y
andl  $65535,%edx           t3 = t1&0xFFFF
imull %edx,%eax             Return t4 = t2*t3

Instead of using leal and then shifting by 4 to multiply z by 48, could I just use imull $48, %eax ?

Also, this is using the %edx register several times. Does this mean t1 is being overwritten? In other words, would I still be able to retrieve t1 right before t4 if I wanted to?

like image 644
Dylan Avatar asked Oct 30 '22 05:10

Dylan


1 Answers

Trying to match assembly to your code line by line probably isn't the best way to approach this. The compiler makes several optimizations to make your program run as efficiently as possible, which is why you may notice some inconsistencies between your code.

To answer your first question, technically that would work, but once again the compiler does make several optimizations. So while it may seem more intuitive to use imul, the compiler determined that leal and sall is more efficient. EDIT: I just want to point out that bit shift operators are almost always used instead of imul, when possible. Bit shifting is much cheaper for the CPU since it quite literally is just shifting bit values rather than trying to perform some mathematical operation that may take more CPU time.

Now regarding "overwriting" t1. Assembly doesn't have any information about your program variables - all it knows is that it needs to perform some operations on some values. While the assembly could potentially use 4 different registers to store t1-4, the compiler determined that it was unnecessary and that you only need 2 registers for all of the values. If you think about it, this should make sense. Your function could be reduced to just a few lines of code. Obviously that isn't a good idea since that would make it impossible to read, but assembly isn't necessarily designed to be "readable". If you went back to your program and performed some other operation with t1 before returning t4, you may notice that your assembly is different than before and that it may be using another register, depending on how the value is used.

If you really want a barebones version of your program in assembly, compile with the -Og flag to turn down compiler optimizations. It may still not exactly match your code, but it might make it easier for you to understand what's going on.

like image 77
Ross Freeman Avatar answered Nov 15 '22 05:11

Ross Freeman