Раздел «Язык Ассемблера».DisassembleSamples:

Опыты дизассемблирования

Рассмотрим ряд простых программ на C и посмотрим на их ассемблерный код , который получим с помощью программы gcc.

/* Программа a1.c*/
#include<stdio.h>
int main()
{
        int i, n = 0;
        for(i=1; i <= 10 ; i++)
        {
                n += i*i;
        }
        printf("%d\n", n);
}

С помощью команды

bash$ gcc a1.c -o a1
можно получть программу, которая выдёёт на стандартный поток вывода сумму квадратов первых 10 натуральных чисел.

Чтобы получить ассемблерный код этой программы, запустите программу gcc с опцией -S

bash$ gcc -S a1.c
Результат выполнения этой оманду будет файл a1.s. Откройте его в текстовом редакторе и изучите содержимое.

Есть возможность получить ассемблерный код, с включенными в него строчками исходного кода на C. Это называется

gcc -c -g -Wa,-a,-ah,-an,-ad a1.c > a1.lst

; программа a1.s
        .file   "a1.c"
        .section        .rodata
.LC0:
        .string "%d\n"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        subl    %eax, %esp
        movl    $0, -8(%ebp)
        movl    $1, -4(%ebp)
.L2:
        cmpl    $10, -4(%ebp)
        jle     .L5
        jmp     .L3
.L5:
        movl    -4(%ebp), %eax
        movl    %eax, %edx
        imull   -4(%ebp), %edx
        leal    -8(%ebp), %eax
        addl    %edx, (%eax)
        leal    -4(%ebp), %eax
        incl    (%eax)
        jmp     .L2
.L3:
        subl    $8, %esp
        pushl   -8(%ebp)
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        leave
        ret
        .size   main, .-main
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.3.3"

Программа 2

Аналогично из программы

#include <stdio.h>
int main()
{
        int n;
        scanf("%d", &n);
        while(n){ printf("%d", n%2 ); n /= 2; }
        putc('\n', stdout);
        return 0;
}

можно получть следующий ассемблерный код:

    .file   "a2.c"
    .section    .rodata
.LC0:
    .string "%d"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    andl    $-16, %esp
    movl    $0, %eax
    subl    %eax, %esp
    subl    $8, %esp
    leal    -4(%ebp), %eax
    pushl   %eax
    pushl   $.LC0
    call    scanf
    addl    $16, %esp
.L2:
    cmpl    $0, -4(%ebp)
    jne .L4
    jmp .L3
.L4:
    subl    $8, %esp
    movl    -4(%ebp), %edx
    movl    %edx, %eax
    sarl    $31, %eax
    shrl    $31, %eax
    leal    (%eax,%edx), %eax
    sarl    $1, %eax
    addl    %eax, %eax
    subl    %eax, %edx
    movl    %edx, %eax
    pushl   %eax
    pushl   $.LC0
    call    printf
    addl    $16, %esp
    movl    -4(%ebp), %edx
    movl    %edx, %eax
    sarl    $31, %eax
    shrl    $31, %eax
    leal    (%eax,%edx), %eax
    sarl    $1, %eax
    movl    %eax, -4(%ebp)
    jmp .L2
.L3:
    subl    $8, %esp
    pushl   stdout
    pushl   $10
    call    _IO_putc
    addl    $16, %esp
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .section    .note.GNU-stack,"",@progbits
    .ident  "GCC: (GNU) 3.3.3"


Q: How can I create a file where I can see the C code and its assembly translation together?

A: Use the -S (note: capital S) switch to GCC, and it will emit the assembly code to a file with a .s extension. For example, the following command:

  gcc -O2 -S -c foo.c

will leave the generated assembly code on the file foo.s.

If you want to see the C code together with the assembly it was converted to, use a command line like this:

 gcc -c -g -Wa,-a,-ad [other GCC options] foo.c > foo.lst

which will output the combined C/assembly listing to the file foo.lst.

If you need to both get the assembly code and to compile/link the program, you can either give the -save-temps option to GCC (which will leave all the temporary files including the .s file in the current directory), or use the -Wa,aln=foo.s option which instructs the assembler to output the assembly translation of the C code (together with the hex machine code and some additional info) to the file named after the =.