Выбор четырех регистров аргументов на x64 - общий для UN * X / Win64
При использовании x86 следует помнить, что имя регистра в кодировке "reg number" неочевидно; с точки зрения кодирования инструкций ( байт MOD R / M , см. http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ), номера регистров 0 ... 7 - в таком порядке - ?AX
, ?CX
, ?DX
, ?BX
, ?SP
, ?BP
, ?SI
, ?DI
.
Следовательно, выбор A / C / D (regs 0..2) для возвращаемого значения и первых двух аргументов (что является «классическим» 32-битным __fastcall
соглашением) является логическим выбором. Что касается перехода на 64-битную версию, то заказываются «более высокие» регистры, и Microsoft и UN * X / Linux выбрали R8
/ R9
как первые.
Имея это в виде, выбор Microsoft по RAX
(возвращаемое значение) и RCX
, RDX
, R8
, R9
(Arg [0..3]) является понятным выбором , если вы выбираете четыре регистра для аргументов.
Я не знаю, почему AMD64 UN * X ABI выбрал RDX
раньше RCX
.
Выбор шести регистров аргументов на x64 - для UN * X
UN * X на архитектурах RISC традиционно выполняет передачу аргументов в регистрах - в частности, для первых шести аргументов (по крайней мере, для PPC, SPARC, MIPS). Это может быть одной из основных причин, по которой разработчики AMD64 (UN * X) ABI решили использовать шесть регистров и в этой архитектуре.
Так что если вы хотите шесть регистров для передачи аргументов в, и это логично выбрать RCX
, RDX
, R8
и R9
четыре из них, которые других двух вы должны выбрать?
«Старшие» регистры требуют дополнительного байта префикса инструкций для их выбора и, следовательно, имеют больший размер инструкции, поэтому вы не захотите выбирать какой-либо из них, если у вас есть опции. Из классических регистров, из - за неявный смысл RBP
и RSP
они не доступны, и RBX
традиционно имеет особое применение на ООН * X (глобальная таблица смещений) , которые , казалось бы , дизайнеры AMD64 ABI не хотели понапрасну стать несовместимым с.
Ergo, единственным выбором были RSI
/ RDI
.
Итак, если вам нужно использовать RSI
/ в RDI
качестве регистров аргументов, какими аргументами они должны быть?
Изготовление их arg[0]
и arg[1]
имеет ряд преимуществ. См. Комментарий cHao.
?SI
и ?DI
являются операндами источника / назначения строковых инструкций, и, как упоминалось в cHao, их использование в качестве регистров аргументов означает, что с соглашениями о вызовах AMD64 UN * X простейшая возможная strcpy()
функция, например, состоит только из двух инструкций ЦП, repz movsb; ret
поскольку источник / цель адреса были помещены вызывающим абонентом в правильные регистры. Есть, в частности, в низкоуровневом и сгенерированном компилятором "связующем" коде (подумайте, например, о некоторых распределителях кучи C ++, заполняющих объекты нулями при создании, или страницы кучи ядра с нулевым заполнением наsbrk()
, или ошибки страницы копирования при записи) огромное количество блоков копирования / заполнения, поэтому это будет полезно для кода, который так часто используется для сохранения двух или трех инструкций ЦП, которые в противном случае загружали бы такие аргументы исходного / целевого адреса в "правильные" регистры.
Таким образом , в некотором смысле, UN * X и Win64 отличаются только тем , что UN * X «помещает» два дополнительных аргумента, в целенаправленно выбранных RSI
/ RDI
регистров, к естественному выбору четырех аргументов в RCX
, RDX
, R8
и R9
.
За гранью этого ...
Между UN * X и Windows x64 ABI есть больше различий, чем просто отображение аргументов в определенные регистры. Для обзора Win64 проверьте:
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Win64 и AMD64 UN * X также разительно отличаются по способу использования пространства стека; в Win64, например, вызывающий должен выделить пространство стека для аргументов функции, даже если в регистрах передаются аргументы 0 ... 3. В UN * X, с другой стороны, листовая функция (то есть та, которая не вызывает другие функции) даже не требуется для выделения пространства стека вообще, если ей требуется не более 128 байтов (да, вы владеете и можете использовать определенное количество стека без выделения его ... ну, если вы не код ядра, источник изящных ошибок). Все это конкретные варианты оптимизации, большая часть обоснования которых объясняется в полных ссылках на ABI, на которые указывает ссылка в Википедии исходного постера.