Вызываемый объект может очистить стек от переменных аргументов. Я сделал это один раз, на самом деле. Но код довольно большой.
В любом случае, основная причина, по которой в соглашении cdecl вызывающая сторона очищает стек, заключается в другом. (В конце концов, процедур с переменными аргументами очень мало)
На некоторых архитектурах (обычно очень маленьких, таких как старые 8080 или 6800) нет инструкции ret n
для автоматизации очистки стека и, как правило, они не могут выполнять арифметические действия с указателем стека.
Таким образом, вызываемая сторона должна сначала извлечь адрес возврата из стека, чтобы получить доступ к аргументам, затем извлечь все аргументы, а затем вернуть адрес возврата. Для 3 аргументов это будет выглядеть так с соглашением stdcall:
push arg1
push arg2
push arg3
call proc
proc:
pop r1 ; the return address
pop r2
pop r2
pop r2
push r1
ret
При использовании соглашения cdecl 2 инструкции и одно использование регистра не используются:
push arg1
push arg2
push arg3
call proc
pop r2
pop r2
pop r2
proc:
ret
И поскольку для одного языка лучше использовать одно соглашение о вызовах на всех платформах, CCALL как более простой и универсальный выглядит лучше. (Язык C создан во времена, когда 6800 был высокотехнологичным).
Но обратите внимание, что на этих платформах ассемблерные программы и родные языки (например, разные типы BASIC) обычно используют передачу аргументов регистра, что, конечно, намного быстрее на таких небольших системах.
В любом случае, это просто традиция. Вы можете настроить компилятор на использование любого соглашения, которое вы хотите. Например, WinAPI написан на C++, но по-прежнему использует соглашение stdcall, потому что оно лучше работает на платформе x86.
person
johnfound
schedule
06.11.2013