Estoy trabajando con algunas funciones de trampolín para utilizar con llamadas de alto nivel en C/Objective-C, un ligero giro en el camino Apple does it.Eliminando argumentos de la pila en i386, ensamblado ARM
Si está familiarizado con la forma en que funciona Objective-C IMP
, básicamente es un puntero de función donde los dos primeros argumentos son el receptor de un mensaje y el nombre del selector de mensajes, como void(*)(id obj, SEL sel, ...)
. Las versiones más recientes del tiempo de ejecución permiten sintetizar implementaciones de métodos en tiempo de ejecución usando bloques C, como void(^)(id obj, ...)
. Estos bloques no tienen el selector; el tiempo de ejecución crea un trampolín que sobrescribe el selector con el receptor, el receptor con el puntero de bloque y luego ejecuta su ejecución.
Quiero hacer algo vagamente similar que no implica tener ya sea de los dos primeros argumentos, por lo que los argumentos a este bloque son exactamente los mismos que los argumentos del método send tradicional, más el indicador de bloque para la ejecución propósitos, es decir, void(*)(Block *, ...)
. Esto solo requiere copiar en el puntero del bloque, y supongo que eliminar un argumento.
__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
Aquí está el ensamblaje tengo en 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]
existe
código similar para el x86_64; el código anterior es, por lo tanto, directamente de Apple. Para conocimiento personal, me pregunto por dónde empezar con la eliminación de una discusión, de modo que el primer argumento (lo que solía ser el receptor) es el literal del bloque, el segundo es el primer argumento real, y así sucesivamente.
Soy increíblemente inocente en ASM, por lo que cualquier ayuda es muy apreciada. Todo lo que probé se ha reventado de maneras cada vez más interesantes. Gracias por adelantado.
Cuidado, muchas distribuciones de Linux se encuentran actualmente en el proceso de pasar al ARM Hard-Float ABI. Eso lo romperá completamente por completo, de nuevo. – ams
Eso es interesante, lo tendré en cuenta para el futuro. Sin embargo, esto se dirige principalmente a Darwin. ¡Gracias! Editar: Eso significa ARMV6 y ARMV7, por el momento, al menos. – zwaldowski