Я продолжаю получать ошибки сегментации. Как стек используется в IA-32 с использованием AT&T?

Для выполнения домашнего задания нас попросили отсканировать число, увеличить его на единицу и распечатать ответ. Тем не менее, код имеет тенденцию давать ошибку сегментации.

.global main

mystring: .asciz "Assignment 3: inout\n"

string: .asciz "%d"

main:   pushl $mystring
        call printf
        jmp inout

end:    pushl $0
        call exit

Это в основном то, что мы делаем. Запуск такого кода без перехода работает. Проблема в методе inout

inout:  subl $0, %esp             ;what is happening here
        leal -4(%ebp), %eax       ;what am i doing here
        pushl %ebp                ;why do i need to push the base pointer
        movl %esp, %ebp
        pushl %eax
        pushl $string
        call scanf
        incl %eax
        pushl %eax
        pushl $string
        call printf

Который, кажется, не работает. Я также понятия не имею, что означает начало (substract, address thing), см. Комментарий для дальнейших вещей. Заранее спасибо!

1 ответ

Решение

Частичный ответ, но, возможно, это поможет вам отследить проблему:

subl $0, %esp вырастил бы стек, если бы константа не была нулевой. Вершина стека обычно находится на самом низком адресе памяти в x86, то есть стеки растут вниз.

leal -4(%ebp), %eax загружает абсолютный адрес %ebp - 4 в %eax, Это указатель на область памяти, где scanf Целое число d должно быть сохранено.

Почему ты push Базовый указатель действительно актуальный вопрос. Вы обычно делаете это, потому что потом модифицируете, делаете вещи, а затем pop это когда вы закончите - что, кажется, вы не делаете. Обычно используется с функциями, которые вы call хоть. Это может быть проблема здесь, вы звоните inout метод, но вы используете его в качестве метки для jmp только. Код, который вы опубликовали, теперь не имеет возможности вернуться туда, где он был jmp ед. из

В Wikibooks есть довольно краткое введение в фреймы стека x86.

Другие вопросы по тегам