Last Updated: 2023-10-02 14:19:01 Monday
-- TOC --
本文通过示例代码,学习for loop循环被编译成汇编的样子。
测试用C代码如下:
#include <stdio.h>
int main(){
for(int i=0; i<100; ++i){
if(i%2 == 0)
printf("%d\n", i);
}
return 0;
}
不开优化,汇编如下:
.LC0:
.string "%d\n"
main:
push rbp
mov rbp, rsp
sub rsp, 16
# i = 0
mov DWORD PTR [rbp-4], 0
jmp .L2
.L4:
# 把i存入eax
mov eax, DWORD PTR [rbp-4]
# i&=0x01
and eax, 1
# i&i
test eax, eax
# if i!=0, goto .L3
jne .L3
# if i==0, prepare and call printf
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
.L3:
# ++i
add DWORD PTR [rbp-4], 1
.L2:
# i - 99
cmp DWORD PTR [rbp-4], 99
# if i <= 99, goto .L4
jle .L4
# for loop end
mov eax, 0
leave
ret
-O1
.LC0:
.string "%d\n"
main:
push rbx
# ebx = i = 0
mov ebx, 0
jmp .L3
.L2:
# ++i
add ebx, 1
# i-100
cmp ebx, 100
# 如果cmp结果是0,goto .L6
je .L6
.L3:
# 只对bl进行测试,bl&0x01
test bl, 1
# 如果结果不为0,即不为偶数,goto .L2
jne .L2
# 结果为0,call printf, goto .L2
mov esi, ebx
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
jmp .L2
.L6:
# for loop end
mov eax, 0
pop rbx
ret
-O2或-O3
.LC0:
.string "%d\n"
main:
push rbx
# 用xor清零
xor ebx, ebx
jmp .L3
.L2:
add ebx, 1
cmp ebx, 100
je .L7
.L3:
test bl, 1
jne .L2
mov esi, ebx
mov edi, OFFSET FLAT:.LC0
# 用xor清零
xor eax, eax
# ++i
add ebx, 1
call printf
# (i-100)!=0, goto .L3
cmp ebx, 100
jne .L3
.L7:
xor eax, eax
pop rbx
ret
O3代码的变化,感觉是某种inline,将判断是否继续循环的代码,放在循环内部,因此出现了两行相同的+1和cmp。
本文链接:https://cs.pynote.net/hd/asm/202302094/
-- EOF --
-- MORE --