Шаблон языка ассемблера.- Простое ленивое соглашение? - PullRequest
1 голос
/ 02 сентября 2010

Я занимаюсь разработкой некоторых функций на языке ассемблера, вначале мои функции передают параметры следующими тремя способами:

  • регистры
  • глобальные данные в разделе .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

1 Ответ

1 голос
/ 02 сентября 2010

Обычно ABI для конкретной платформы определяет соглашение о вызовах , в котором указывается, что делать с каждым регистром.Простое соглашение может заключаться в том, что любая функция, которую вы вызываете, может удалять eax, ebx и edx, но ecx, esi и edi будут сохраняться вызываемой функцией.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...