Tôi đang lập trình C trên cửa sổ Cygwin. Sau khi đã thực hiện một chút lập trình C và cảm thấy thoải mái với ngôn ngữ, tôi muốn xem xét dưới mui xe và xem những gì trình biên dịch đang làm cho mã mà tôi viết.Trường hợp chuyển đổi mã mức lắp ráp
Vì vậy, tôi đã viết xuống một khối mã có chứa báo cáo trường hợp chuyển đổi và chuyển đổi chúng thành lắp ráp sử dụng:
gcc -S foo.c
Đây là nguồn C:
switch(i)
{
case 1:
{
printf("Case 1\n");
break;
}
case 2:
{ printf("Case 2\n");
break;
}
case 3:
{
printf("Case 3\n");
break;
}
case 4:
{
printf("Case 4\n");
break;
}
case 5:
{
printf("Case 5\n");
break;
}
case 6:
{
printf("Case 6\n");
break;
}
case 7:
{
printf("Case 7\n");
break;
}
case 8:
{
printf("Case 8\n");
break;
}
case 9:
{
printf("Case 9\n");
break;
}
case 10:
{
printf("Case 10\n");
break;
}
default:
{
printf("Nothing\n");
break;
}
}
Bây giờ lắp ráp kết quả cho cùng là :
movl $5, -4(%ebp)
cmpl $10, -4(%ebp)
ja L13
movl -4(%ebp), %eax
sall $2, %eax
movl L14(%eax), %eax
jmp *%eax
.section .rdata,"dr"
.align 4
L14:
.long L13
.long L3
.long L4
.long L5
.long L6
.long L7
.long L8
.long L9
.long L10
.long L11
.long L12
.text
L3:
movl $LC0, (%esp)
call _printf
jmp L2
L4:
movl $LC1, (%esp)
call _printf
jmp L2
L5:
movl $LC2, (%esp)
call _printf
jmp L2
L6:
movl $LC3, (%esp)
call _printf
jmp L2
L7:
movl $LC4, (%esp)
call _printf
jmp L2
L8:
movl $LC5, (%esp)
call _printf
jmp L2
L9:
movl $LC6, (%esp)
call _printf
jmp L2
L10:
movl $LC7, (%esp)
call _printf
jmp L2
L11:
movl $LC8, (%esp)
call _printf
jmp L2
L12:
movl $LC9, (%esp)
call _printf
jmp L2
L13:
movl $LC10, (%esp)
call _printf
L2:
Bây giờ, trong hội đồng, mã đầu tiên kiểm tra trường hợp cuối cùng (ví dụ: trường hợp 10) đầu tiên. Điều này rất lạ. Và sau đó nó được sao chép 'i' vào 'eax' và làm những thứ vượt ra ngoài tôi.
Tôi đã nghe nói rằng trình biên dịch thực hiện một số bước nhảy cho switch..case. Có phải mã này đang làm gì không? Hoặc nó đang làm gì và tại sao? Bởi vì trong trường hợp số ít trường hợp, mã này khá giống với mã được tạo cho nếu ... khác bậc thang, nhưng khi số lượng các trường hợp tăng lên, việc thực hiện trông lạ thường này được nhìn thấy.
Xin cảm ơn trước.
Thật không may là nó không tối ưu hóa việc tìm kiếm bảng con trỏ chuỗi và 'cuộc gọi _printf'. Không có gcc/clang/icc nào làm điều đó ngay cả ở '-O3'. https://godbolt.org/g/JrSwU3 (Tuy nhiên, chúng tối ưu hóa 'printf' thành' puts', và tối ưu hóa đuôi gọi đến 'jmp' thay vì' call'/'ret') –