Обычно, чтобы выполнять вызовы быстрее (в зависимости от архитектуры), компилятор может выбрать передачу некоторых параметров через регистры, чтобы каждый раз не копировать их в / из стека. Это особенно верно для частных функций, которые не экспортируются и, следовательно, не обязаны подчиняться соглашениям о вызовах, определенным ABI, для дальнейшей оптимизации.
Некоторые ABI фактически требуют параметров для передаваться в регистры. Соглашение о вызовах System V AMD64 ABI (по умолчанию Linux x86-64) является отличным примером этого: оно требует, чтобы параметры функции передавались через RDI, RSI, RDX, RCX, R8, R9, [XYZ] MM0– 7, поэтому стек используется очень редко.
Теперь при выполнении системного вызова в Linux ядро копирует регистры пользовательского пространства в стек, чтобы сохранить их, а затем вызывает соответствующую функцию системного вызова. Эти функции должны принимать параметры непосредственно из уже сохраненных пользовательских регистров в стеке и поэтому должны быть скомпилированы только и всегда принимать параметры из стека.
In x86 32bit, asmlinkage
макрос расширяется до __attribute__((regparam(0)))
, что в основном сообщает G CC, что никакие параметры не должны передаваться через регистры (0
является важной частью ). На 64-битной x86 он заменяется на более конкретный c __attribute__((syscall_linkage))
. Конечный результат тот же: функция вынуждена брать параметры из стека. На других архитектурах, которые всегда передают параметры в стек, никакого специального __attribute__
даже не требуется.