Я занимаюсь разработкой некоторых функций на языке ассемблера, вначале мои функции передают параметры следующими тремя способами:
- регистры
- глобальные данные в разделе .data
- через стек
Теперь я обнаружил, что сочетание трех вышеперечисленных способов усложняет ситуацию.И я всегда попадаю в ситуацию, когда мне приходится чесать голову, чтобы удостовериться, не загрязнен ли определенный регистр.Поэтому я решил передать параметры только через стек .И используйте следующий шаблон функции в качестве ленивого разового решения:
pushl %ebp
movl %esp, %ebp
pushal <--- save all the registers, this is kind of a lazy solution
subl xxx, %esp <--- allocate space for local variables
....
popal <--- restore all the registers
movl %ebp, %esp
popl %ebp
(addl yyy, %esp)<--- if it is __stdcall convention, the callee will clear the stack
ret
(xxx - размер локальных переменных, yyy - размер параметров, выдвигаемых вызывающей стороной.)
Вызывающий отвечает за параметры push и очищает стек (например, соглашение о вызове C).Конечно, если число параметров фиксировано, я могу заставить вызываемого пользователя очистить стек (например, соглашение __stdcall в Windows).
Я надеюсь, что этот шаблон может избавить меня от путаницы при использовании регистров.Может ли это достичь этого?Если это низкая эффективность, есть ли лучший подход?Я хотел бы услышать ваш комментарий.
Большое спасибо.
Обновление 1
Привет еще раз, мой код содержит ошибки, поэтому я исправил это так:
pushl %ebp
movl %esp, %ebp
pushal <--- save all the registers, this is kind of a lazy solution
subl xxx, %esp <--- allocate space for local variables
....
addl xxx, %esp <--- reclaim the space for local variables
popal <--- restore all the registers
movl %ebp, %esp
popl %ebp
ret yyy <--- for __stdcall convention, the callee will clear the parameters pushed on stack by caller