Что делает следующая сборка для следующего файла .c - PullRequest
3 голосов
/ 15 февраля 2012

Я написал следующий код, можете ли вы объяснить мне, что здесь говорит сборка?

typedef struct
{
    int abcd[5];
} hh;

void main()
{
    printf("%d", ((hh*)0)+1);
}  

Монтаж:

        .file   "aa.c"
        .section        ".rodata"
        .align 8
.LLC0:

        .asciz  "%d\n"
        .section        ".text"
        .align 4
        .global main
        .type   main, #function
        .proc   020
main:

        save    %sp, -112, %sp
        sethi   %hi(.LLC0), %g1
        or      %g1, %lo(.LLC0), %o0
        mov     20, %o1
        call    printf, 0
         nop
        return  %i7+8
         nop
        .size   main, .-main
        .ident  "GCC: (GNU) 4.2.1"

Ответы [ 2 ]

5 голосов
/ 15 февраля 2012

Ого, язык ассемблера SPARC, я не видел этого в годах .

Я думаю, мы идем строка за строкой? Я собираюсь пропустить некоторые неинтересные шаблоны.

        .section        ".rodata"
        .align 8
.LLC0:
        .asciz  "%d\n"

Это строковая константа, которую вы использовали в printf (это очевидно, я знаю!) Важно отметить, что она находится в разделе .rodata (разделы являются разделами возможного исполняемого образа; этот предназначен для «данные только для чтения» и фактически будут неизменяемыми во время выполнения) и что им был присвоен ярлык .LLC0. Метки, начинающиеся с точки, являются частными для объектного файла. Позже компилятор будет ссылаться на эту метку, когда захочет загрузить адрес строковой константы.

        .section        ".text"
        .align 4
        .global main
        .type   main, #function
        .proc   020
main:

.text - раздел для действительного машинного кода. Это стандартный заголовок для определения глобальной функции с именем main, которая на уровне сборки ничем не отличается от любой другой функции (в C - не обязательно так в C ++). Я не помню, что делает .proc 020.

        save    %sp, -112, %sp

Сохранить предыдущее окно регистра и отрегулировать указатель стека вниз. Если вы не знаете, что такое окно регистров, вам нужно прочитать руководство по архитектуре: http://www.sparc.org/standards/V8.pdf. (V8 - последняя 32-битная итерация SPARC, V9 - первая 64-битная. быть 32-битным кодом.)

        sethi   %hi(.LLC0), %g1
        or      %g1, %lo(.LLC0), %o0

Эта последовательность из двух команд имеет чистый эффект загрузки адреса .LLC0 (это ваша строковая константа) в регистр %o0, который является первым регистром исходящих аргументов. (Аргументы до этой функции находятся в входящих * регистрах аргументов .)

        mov     100, %o1

Загрузить непосредственную константу 100 в %o1, второй регистр исходящего аргумента. Это значение, рассчитанное по ((foo *)0)+5. Это 100, потому что ваш struct foo имеет длину 20 байт (пять 4-байтовых int с), и вы запросили пятый после нуля адреса.

        call    printf, 0
        nop

Звоните printf. nop заполняет интервал задержки (опять же, прочитайте руководство по архитектуре). Я не помню, для чего нужен ноль.

        return  %i7+8
        nop

Перейти к адресу в регистре %i7 плюс восемь. Это имеет эффект возврата из текущей функции. В слоте задержки должна быть должна быть инструкция restore, я не знаю, почему ее там нет.

1 голос
/ 15 февраля 2012

Сборка вызывает printf, передавая ваш текстовый буфер и число 20 в стеке (это то, что вы просили окольным путем).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...