Удаление аргументов из стека в i386, сборка ARM

Я работаю с некоторыми функциями батута для использования с высокоуровневыми вызовами в C/Objective-C, небольшой поворот в пути Apple делает это.

Если вы вообще знакомы с тем, как работает Objective-C IMP, это в основном указатель на функцию, где первые два аргумента — получатель сообщения и имя селектора сообщения, например as void(*)(id obj, SEL sel, ...). Более поздние версии среды выполнения позволяют синтезировать реализации методов во время выполнения с использованием блоков C, например void(^)(id obj, ...). Эти блоки не имеют селектора; среда выполнения создает батут, который перезаписывает селектор с помощью получателя, получателя с указателем блока, а затем переходит к его выполнению.

Я хочу сделать что-то отдаленно похожее, которое предполагает отсутствие ни из первых двух аргументов, чтобы аргументы этого блока были точно такими же, как аргументы традиционного метода send, плюс блок указатель для выполнения, т. е. void(*)(Block *, ...). Это требует только копирования указателя блока и, я полагаю, избавления от аргумента.

__a1a2_tramphead_argonly:
    popl %eax
    andl $0xFFFFFFF8, %eax
    subl $0x1000, %eax
    movl 4(%esp), %ecx // self -> ecx
    movl %ecx, 8(%esp) // ecx -> _cmd
    movl (%eax), %ecx // blockPtr -> ecx
    movl %ecx, 4(%esp) // ecx -> self
    jmp  *12(%ecx) // tail to block->invoke

Вот сборка, которая у меня есть на ARM:

__a1a2_tramphead_argonly:
    // calculate the trampoline's index (512 entries, 8 bytes each)
#ifdef _ARM_ARCH_7
    // PC bias is only 4, no need to correct with 8-byte trampolines
    ubfx r1, r1, #3, #9
#else
    sub  r1, r1, #8               // correct PC bias
    lsl  r1, r1, #20
    lsr  r1, r1, #23
#endif

    // load block pointer from trampoline's data
    adr  r12, __a1a2_tramphead_argonly    // text page
    sub  r12, r12, #4096          // data page precedes text page
    ldr  r12, [r12, r1, LSL #3]   // load block pointer from data + index*8

    // shuffle parameters
    mov  r1, r0                   // _cmd = self
    mov  r0, r12                  // self = block pointer

    // tail call block->invoke
    ldr  pc, [r12, #12]

Аналогичный код существует для x86_64; приведенный выше код пока что напрямую от Apple.Для личного сведения мне интересно, с чего начать с вырезания аргумента, чтобы первый аргумент (то, что раньше было получателем) был литералом блока, второй - первым реальным аргументом и так далее.

Я невероятный нуб в ASM, поэтому любая помощь приветствуется. Все, что я пробовал, взрывалось все более интересными способами. Заранее спасибо.

8
задан zwaldowski 3 April 2012 в 00:48
поделиться