2015-02-13 3 views
1

Я пытаюсь принять это C-код и превратить его в АссамблееАссамблея Сегментация вина: 11

#include <stdlib.h> 

int sub(int x, int y) { 
    return 2*x+y; 
} 

int main(int argc, char ** argv) { 
    int a; 
    a = atoi(argv[1]); 
    return sub(argc,a); 
} 

Я использовал gcc -S math.c, чтобы превратить его в Ассамблее, и, наконец, понял, большинство того, что он делает. Так что я переписал его, как это:

.globl _main 

_sub: 
    push %ebp 
    mov %esp, %ebp 
    mov 0x8(%ebp), %eax   # int x 
    mov 0xC(%ebp), %ecx   # int y 
    lea (%ecx, %eax, 2), %eax # 2 * x + y 
    pop %ebp 
    ret 

_main: 
    push %ebp 
    mov %esp, %ebp 
    sub $0x4, %esp    # int a 
    mov 0xC(%ebp), %eax 
    push 0x4(%eax)    # char* argv[1] 
    call _atoi 
    add $0x4, %esp 
    push %eax     # int y 
    push 0x8(%ebp)    # int x/argc 
    call _sub 
    mov %ebp, %esp 
    pop %ebp 
    ret 

Я использую gcc -m32 -Wall math.s -o math скомпилировать его на OS X, и он прекрасно работает. Но строка sub $0x4, %esp кажется мне очень ненужной. Поэтому я попытался удалить его, и он компилируется отлично. Но когда я запускаю его, используя ./math 2 без этой строки, он дает мне ошибку Segmentation fault: 11.

Я не вижу линий, которые выглядят так, как будто они зависят от этой линии. Поэтому мне интересно, почему эта программа нуждается в этой строке и почему ее удаление вызывает эту ошибку? Благодаря!

+0

Очевидно, вы не писать код, если вы не знаете, что это значит. Позаботьтесь о пересмотре своей истории? –

+0

Ну, он был сгенерирован из gcc и скрипта C, но затем я попытался переписать с нуля, и это то, что я получил. – Addison

+0

Если вы планируете включить это, ваш учитель узнает, что вы сами не пишете программу, так как она пахнет кодом, сгенерированным компилятором. Вам лучше начать с нуля. –

ответ

2

Прежде всего, строка «sub $ 4,% esp» не связана с переменной «a»!

Функция «_atoi» использует регистры XMM, поэтому определенные переменные должны быть выровнены с 16-байтной границей. Чтобы архивировать это для локальных переменных в стеке, есть две возможности:

Функция, называемая («_atoi»), должна гарантировать, что стек выровнен с 16 байтами. Это можно сделать, используя следующий код:

push %ebp 
mov %esp, %ebp 
and $0xFFFFFFF0, %esp # <- This line here 
sub $0x1230, %esp 

Этот подход осуществляется 32-разрядных программ для Windows и Linux так что ваша программа будет работать нормально на Windows, и Linux (я пробовал, что под Windows)!

Под MacOS X вторая возможность используется для 32-битных программ - которая также используется на большинстве операционных систем для 64-битных программ:

При вызове функции стек уже должен быть выровнен до 16 байтов.

Ваша программа с линией «к югу»:

# Here esp is esp_original 
call _main  # 4 bytes 
push %ebp  # 4 bytes 
sub $0x4, %esp # 4 bytes 
push 0x4(%eax) # 4 bytes 
# Here esp must be esp_original+16*N 
call _atoi 

Если удалить «подменю» команду или заменить его на «суб $ 8,% особ» инструкции, то стек больше не выровнены. Из-за этого вам потребуется еще 8 байтов стека, из-за чего вам нужно выполнить «sub $ 20,% esp», а не «sub $ 4,% esp».

К сожалению, это требование делает монтаж программирование более трудным - особенно для начинающих - на MacOS X.

Смежные вопросы