Я продолжаю получать ошибки сегментации. Как стек используется в 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.