Выполнение main
никогда не достигает нижней части функции, поэтому очистка стека никогда не должна происходить; exit()
- это функция «noreturn».
Если main
действительно хочет вернуться с jr $ra
вместо системного вызова exit
, вам необходимо восстановить указатель стека вместе с другими сохраненными вызовами регистрами. В противном случае вы нарушили бы соглашение о вызовах, которое ожидает вызывающий main
main
.
(Обновлено, поскольку вы добавили asm к вопросу, использующему системный вызов MARS: main
возможно, это не функция, если она находится в верхней части вашего кода: $ra
не является допустимым адресом возврата в записи, поэтому он не может вернуться. IMO не вызывайте его main
, если это не функция.)
Операционная система не заботится о том, куда указывает указатель стека пользовательского пространства, когда процесс выполняет системный вызов выхода, поэтому main
не нужно очищать перед выходом.
(В «нормальной» реализации C функция exit()
будет компилироваться в jal exit
или простой вызов хвоста j exit
. Но вы компилируете вручную для симулятора MARS, у которого нет C library, так что вы вызываете системные вызовы вместо вызова функций-оболочек.)
Также обратите внимание, что ISO C exit(int)
принимает аргумент, например MARS exit2
(syscall
/ * 1033) *) . На самом деле вы даже не вызывали exit()
как функцию, вы просто написали exit;
в C, которая оценивает exit
как указатель на функцию, не вызывая ее и ничего не делая с этим значением.
Обычно C main
вызывается кодом запуска CRT, который может, например, запускать C функции инициализации библиотеки и помещать arg c и указатель argv [] в правые регистры. Так что main
обычно не является реальной точкой входа процесса из ОС, особенно в размещенной реализации. (т.е. скомпилированные C программы работают под ОС, а не являются собственным ядром, как отдельная программа.)
Если вы просто переводите это для симуляторов MARS или SPIM или чего-то еще, то нет C библиотека или любой другой код, кроме того, что вы пишете, , поэтому вы пишете то, что обычно называется _start
, а не main
.
In C main
- это функция, но в MARS вы не можете jr $ra
от точки входа верхнего уровня , поэтому точка входа не является функцией . Поэтому не называйте это main
.
В ISO C даже main
даже законно вызывать себя рекурсивно, или другие функции вызывать main
. Это может работать только в том случае, если main действительно является функцией, которая очищает стек и возвращает корректно. Но это означает, что это также не может быть точка входа в процесс, которая должна сделать системный вызов exit
. Чтобы запустить программу с безумной рекурсивной функцией main, которая в конечном итоге выполняет оператор C return
(или падает с конца main), main в значительной степени должна быть скомпилирована в реальную функцию, которая может возвращаться с jr $ra
. Так что это должна быть функция, которую вы jal main
выполняете из своей _start
точки входа.