#c #event-handling
#c #обработка событий
Вопрос:
Я наблюдал за этим обсуждением C Con https://www.youtube.com/watch?v=e8SyxB3_mnwamp;t=2933samp;ab_channel=CppCon где было дано что-то вроде следующего кода (https://godbolt.org/z/av4Tbn ):
struct Handler {
void handle(int x, int y, int z);
static void callback0(void *instance, int x, int y, int z) {
static_cast<Handler *>(instance)->handle(x, y, z);
}
static void callback1(int x, int y, int z, void *instance) {
static_cast<Handler *>(instance)->handle(x, y, z);
}
};
auto c0 = Handler::callback0;
auto c1 = Handler::callback1;
Этот код создает следующую сборку:
Handler::callback0(void*, int, int, int):
jmp Handler::handle(int, int, int)
Handler::callback1(int, int, int, void*):
mov r8d, edi
mov rdi, rcx
mov ecx, edx
mov edx, esi
mov esi, r8d
jmp Handler::handle(int, int, int)
c1:
.quad Handler::callback1(int, int, int, void*)
c0:
.quad Handler::callback0(void*, int, int, int)
Очевидно, что callback0 является предпочтительной версией здесь, но я не понимаю, что происходит «под капотом» в callback1? Может кто-нибудь уточнить?
Ответ №1:
В callback0()
, аргументы передаются через регистры процессора в точном порядке, который handle()
их ожидает, где instance
становится handler
this
указателем, поэтому нет необходимости переставлять какие-либо значения, следовательно, почему jmp
используется само по себе.
В callback1
, аргументы должны быть переставлены в правильные регистры процессора, где handle()
их ожидают, прежде чем jmp
затем может быть вызван.
Это связано с тем, как работает передача аргументов в различных соглашениях о вызовах.