Example C to Assembly Translations

Let's look at a how a real compiler does its translations at various optimization levels.

An Example C Program

gcd.c
/*
 * gcd.c
 *
 * A GCD function.
 */

unsigned gcd(unsigned x, unsigned y) {
    while (y > 0) {
        unsigned old_x = x;
        x = y;
        y = old_x % y;
    }
    return x;
}

Translations with GCC

No Optimizations

$ gcc -S -o gcd0.s gcd.c
        .file	"gcd.c"
        .text
        .globl gcd
        .type	gcd, @function
gcd:
.LFB0:
        .cfi_startproc
        pushq	%rbp
        .cfi_def_cfa_offset 16
        movq	%rsp, %rbp
        .cfi_offset 6, -16
        .cfi_def_cfa_register 6
        movl	%edi, -20(%rbp)
        movl	%esi, -24(%rbp)
        jmp	.L2
.L3:
        movl	-20(%rbp), %eax
        movl	%eax, -4(%rbp)
        movl	-24(%rbp), %eax
        movl	%eax, -20(%rbp)
        movl	-4(%rbp), %eax
        movl	$0, %edx
        divl	-24(%rbp)
        movl	%edx, -24(%rbp)
.L2:
        cmpl	$0, -24(%rbp)
        jne	.L3
        movl	-20(%rbp), %eax
        leave
        ret
        .cfi_endproc
.LFE0:
        .size	gcd, .-gcd
        .ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5.1) 4.4.5"
        .section	.note.GNU-stack,"",@progbits

Optimization Level 1

$ gcc -S -O1 -o gcd1.s gcd.c
        .file	"gcd.c"
        .text
        .globl gcd
        .type	gcd, @function
gcd:
.LFB0:
        .cfi_startproc
        movl	%edi, %eax
        testl	%esi, %esi
        je	.L2
.L6:
        movl	$0, %edx
        divl	%esi
        testl	%edx, %edx
        je	.L3
        movl	%esi, %eax
        movl	%edx, %esi
        jmp	.L6
.L3:
        movl	%esi, %eax
.L2:
        rep
        ret
        .cfi_endproc
.LFE0:
        .size	gcd, .-gcd
        .ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5.1) 4.4.5"
        .section	.note.GNU-stack,"",@progbits

Optimization Level 3

$ gcc -S -O3 -o gcd3.s gcd.c
        .file	"gcd.c"
        .text
        .p2align 4,,15
        .globl gcd
        .type	gcd, @function
gcd:
.LFB0:
        .cfi_startproc
        testl	%esi, %esi
        movl	%edi, %eax
        jne	.L6
        jmp	.L2
        .p2align 4,,10
        .p2align 3
.L8:
        movl	%edx, %esi
.L6:
        xorl	%edx, %edx
        divl	%esi
        movl	%esi, %eax
        testl	%edx, %edx
        jne	.L8
.L2:
        rep
        ret
        .cfi_endproc
.LFE0:
        .size	gcd, .-gcd
        .ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5.1) 4.4.5"
        .section	.note.GNU-stack,"",@progbits