Я хочу написать встроенную сопрограмму в своем Apple Silicon Macbook. Поскольку встроенной сопрограмме нужен jmp_buf
в setjmp.h
, я попытался выяснить, какие регистры хранятся в jmp_buf
.
Когда я захожу в файл setjmp.h
в /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/usr/include/setjmp.h
, я только что узнал код, но он кажется немного странным.
Код:
/*
* _JBLEN is the number of ints required to save the following:
* r21-r29, sp, fp, lr == 12 registers, 8 bytes each. d8-d15
* are another 8 registers, each 8 bytes long. (aapcs64 specifies
* that only 64-bit versions of FP registers need to be saved).
* Finally, two 8-byte fields for signal handling purposes.
*/
#define _JBLEN ((14 + 8 + 2) * 2)
typedef int jmp_buf[_JBLEN];
typedef int sigjmp_buf[_JBLEN + 1];
#else
# error Undefined platform for setjmp
#endif
Кажется, что _JBLEN
определено как 14 + 8 регистров, но в комментарии указано 12 + 8. Как говорится в другом сообщении, в арке Arm64 x19-x28 — это сохраненные регистры вызываемого абонента, которые следует сохранить, а также x29(fp), x30(lr), x31(sp ), компьютер также следует сохранить. В этом случае 14 регистров имеют смысл. Комментарий неправильный или мои расчеты неверны?
Как мне выяснить, какие именно регистры сохранены в jmp_buf, и если комментарий MacOSX sdk неверен, как я могу его исправить?
Когда в комментарии написано «12», а в коде — «14», разве не очевидно, что не так?
Но я хочу знать, как именно эти регистры хранятся в jmp_buf, потому что для реализации собственной сопрограммы мне нужно изменить значения sp и pc в jmp_buf. Мне недостаточно знать, что комментарий неправильный, мне также нужно знать, что правильно.
Комментарий явно неправильный, так как в нем отсутствуют x19
и x20
, но упоминаются x29
и fp
, которые являются одним и тем же.
Вот что ABI объявляет как сохраненное вызываемым абонентом:
x19
до x30
(включает x29
= fp
и x0
= lr
)1q8
до q15
, т. е. d8
-d15
sp
Сохранять pc
нет смысла, так как вы знаете, откуда сейчас выполняете. Так что очень нужно 13 + 8
.
Дампы исходного кода Apple действительно включают реализацию setjmp
, но этот дамп исходного кода является ложью, поскольку фактическая реализация, используемая в производстве, использует аутентификацию указателя и до сих пор является закрытым исходным кодом. Я мог бы поручить вам эту разборку, но думаю, что это будет плохая идея. Вся причина, по которой jmp_buf
объявлен как непрозрачный большой двоичный объект, заключается в том, что его макет является частным, а реализации setjmp
и longjmp
разрешены для изменения.
Если вам нужна возможность изменять jmp_buf
, то лучше просто написать свои собственные ассемблерные процедуры, которые разгружают/перезагружают регистры, сохраненные вызываемым абонентом.
1x30
сохраняется в вызываемом объекте в том смысле, что ожидается, что функция вернется туда. Но в контексте setjmp
его нужно сохранить.
Спасибо, что объяснили мне это, в таком случае, я думаю, мне следует найти другой способ реализовать свою работу, а не модифицировать ее jmp_buf
Мне кажется, что ответ на этот вопрос должен полностью зависеть от компилятора. Страницы руководства — полезное чтение, но в основном они сводятся к тому, что «некоторые регистры сохранены».