Mee*_*cus 5 c x86 assembly intel
我编译了这个C函数:
int calc(int x, int y, int z) {
return x + 3*y + 19*z;
}
Run Code Online (Sandbox Code Playgroud)
我在calc.s中得到了这个,我正在注释正在发生的事情:
.file "calc.c"
.text
.globl calc
.type calc, @function
calc:
pushl %ebp //Save paramaters
movl %esp, %ebp //Move stack pointer into %ebp
movl 12(%ebp), %eax //Move y into %eax
movl 16(%ebp), %ecx //Move z into %ecx
leal (%eax,%eax,2), %eax //%eax = 3*y
addl 8(%ebp), %eax //%eax = x+3y
leal (%ecx,%ecx,8), %edx // ?
leal (%ecx,%edx,2), %edx // ?
addl %edx, %eax //%eax = (x+3*y)+(19*z)
popl %ebp //Pop the previous pointer
ret
.size calc, .-calc
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
我理解最后两个leal指令的一切.为什么你需要两个19*z的leal指令,而3*y是在一个指令中完成的.
leal如果常数是2加1的幂,则是以便宜的方式执行乘以小常数的方法.这个想法是没有偏移的leal相当于"Reg1 = Reg2 + Reg3*Scale".如果Reg2和Reg3恰好匹配,则表示"Reg1 = Reg2*(Scale + 1).
leal 只支持最多8的比例因子,所以要乘以19,你需要两个.
的效果
leal (%eax,%eax,2), %eax
Run Code Online (Sandbox Code Playgroud)
是:
eax = eax + eax*2
Run Code Online (Sandbox Code Playgroud)
也就是说,乘以三.
第二个两个leal一起执行乘以19:
leal (%ecx,%ecx,8), %edx // edx = ecx+ecx*8
leal (%ecx,%edx,2), %edx // edx = ecx+edx*2 (but edx is already z*9)
Run Code Online (Sandbox Code Playgroud)