2013-04-28 2 views
3

Я пытаюсь понять, как создается сборка для c. Я написал образец программы и разобрал ее для того же самого.Инструкции по сборке для функции с указателем как локальной переменной

int main() 
{ 
int a = 100; 
} 

Ассамблея генерироваться:

pushq %rbp  # 
movq %rsp, %rbp #, 
subq $48, %rsp #, 
call __main # 
movl $100, -4(%rbp) #, a 
leave 
ret 

Это довольно прямо вперед для меня. Но я не понимаю сборку, когда включаю в нее указатель.

C Программа:

int main() 
{ 
int a = 100; 
int *p = &a; 
} 

Ассамблея генерироваться:

pushq %rbp  # 
movq %rsp, %rbp #, 
subq $48, %rsp #, 
call __main # 
movl $100, -12(%rbp) #, a 
leaq -12(%rbp), %rax #, tmp59 
movq %rax, -8(%rbp) # tmp59, p 
leave 
ret 

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

Вопрос №2: Если у меня есть 4 локальных переменных, то мой стек кадров составляет $ 48,% rsp, но если я конвертирую одну из локальных переменных в указатель, это подкласс $ 64. почему это так.

код C:

int main() 
{ 
int a = 100; 
int *p = &a; 
int b = 10; 
int c = 20; 
} 

Монтаж:

pushq %rbp  # 
movq %rsp, %rbp #, 
subq $64, %rsp #, 
call __main # 
movl $100, -20(%rbp) #, a 
leaq -20(%rbp), %rax #, tmp59 
movq %rax, -8(%rbp) # tmp59, p 
movl $10, -12(%rbp) #, b 
movl $20, -16(%rbp) #, c 
leave 
ret 

Кроме того, было бы полезно, если бы вы, ребята, можете объяснить, почему стек кадр 2 * 16 байт выровненные (32 байта) для основная функция без локальных переменных. Угадайте, что это должно быть для некоторых упражнений по хранению книг, но какая именно причина?

Спасибо,

+4

Компилятор может помещать переменные в любом месте в стек, который он хочет. – Mysticial

+0

Спасибо Мистический. Тем не менее у меня есть еще один вопрос. Я опубликовал вопрос в той же теме. Тем не менее он слишком велик, чтобы добавить в качестве комментария. – trialyogi

+0

@trialyogi? у вас есть две локальные переменные: 'a' и' p'. 100 - это константа времени компиляции, а адрес 'a' используется в присваивании ... но с правой стороны (не слева). Вы можете видеть в сборке, что компилятор выделил 8 байтов с наивысшим адресом в фрейме стека для 'p', а затем 4 байта ниже, чем для' a'. – rliu

ответ

0

Компилятор не просто преобразующий код построчно от с до сборки. Оптимизация компиляторов проведет кучу анализа кода, пытающегося сделать такие вещи, как удаление кода, который никогда не будет выполнен, оптимизация производительности цикла и оптимизация использования стека/памяти. К тому моменту, когда компилятор решает, где распределять память и где хранить переменные, он знает об а и р и будет размещать их там, где это считается лучшим.

0

Ну, в x86_64 указатель стека всегда хранится с выравниванием по 16 байт (поэтому использование инструкций загрузки/хранения sse 16 байтов будет наиболее эффективным). Указатели имеют 8 байтов и требуют только 8-байтового выравнивания, а int - 4 байта и требуют только 4 байтового выравнивания. Порядок локальных варов в кадре стека полностью неопределен, но в целом компиляторы сначала выложит те, у кого наибольшие ограничения выравнивания, а затем те, которые более гибкие (чтобы наиболее эффективно упаковывать). Компилятор может также зарезервировать место для других вещей (проливные регистры и пространство для исходящих аргументов в вызовах) и полагаться на то, что мертвый код оптимизатора устраняет все, что не нужно (поэтому, если вы компилируете без оптимизации, вы увидите много видимо, неиспользуемого пространства в стеке).