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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With