Last Updated: 2023-10-02 14:19:01 Monday
-- TOC --
本文通过示例代码,学习if...else...结构被编译成汇编是什么样的。
测试用C代码如下:
#include <stdio.h>
int main(){
int a = 1;
int b = 2;
int c = 3;
int d = 4;
if((a>b)&&(c>d)){
printf("%d\n", a+c);
} else {
printf("%d\n", b+d);
}
int e = (a+b)/(c+d);
return e;
}
不开优化,汇编如下:
.LC0:
.string "%d\n"
main:
push rbp
mov rbp, rsp
sub rsp, 32
mov DWORD PTR [rbp-4], 1
mov DWORD PTR [rbp-8], 2
mov DWORD PTR [rbp-12], 3
mov DWORD PTR [rbp-16], 4
# 把a存入eax
mov eax, DWORD PTR [rbp-4]
# a - b
cmp eax, DWORD PTR [rbp-8]
# if a <= b, goto .L2
# 后面的c>d就不判断了!
jle .L2
# a > b, 把c存入eax
mov eax, DWORD PTR [rbp-12]
# c - d
cmp eax, DWORD PTR [rbp-16]
# if c <= d, goto .L2
jle .L2
# if((a>b)&&(c>d)) is true
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-12]
# a+c的结果放入eax
add eax, edx
# 准备call printf,两个参数
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
# 离开if...else...结构
jmp .L3
.L2:
# if((a>b)&&(c>d)) is false
mov edx, DWORD PTR [rbp-8]
mov eax, DWORD PTR [rbp-16]
# b+d的结果放入eax
add eax, edx
# 准备call printf, 两个参数
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
.L3:
# 重新计算a+c和b+d
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-8]
# eax = a+c
add eax, edx
mov ecx, DWORD PTR [rbp-12]
mov edx, DWORD PTR [rbp-16]
# ecx = b+d
add ecx, edx
# 有符号扩展eax到edx,edx:eax是dividend
cdq
# ecx是divisor
# quotient在eax,remainder在edx
idiv ecx
mov DWORD PTR [rbp-20], eax
# quotient存入eax
mov eax, DWORD PTR [rbp-20]
leave
ret
如果开优化,只是-O1
,整个if...else...结构就被优化没有了。
在汇编层面,jmp就像goto,jmp是必须的。我觉得,在C语言层面,只要不影响代码的可读性,还是可以看情况使用goto的。
汇编是面向寄存器编程,所有数据结构都在程序员心中,需要程序员自己编写实现调用栈。C是面向内存编程,看不见寄存器,调用栈自动就有。Python连内存都基本看不到了...
本文链接:https://cs.pynote.net/hd/asm/202302093/
-- EOF --
-- MORE --