ver http://github.com/dwelch67/yagbat qemu directorio.
Aquí hay un par de ejemplos de llamar brazo o el pulgar del brazo
start_vector:
mov sp,#0x20000
;@ call an arm function from arm
bl notmain
;@ call a thumb function frm arm
ldr r0,=0xAABBAABB
bl hexstring_trampoline
;@ call a thumb function frm arm
ldr r0,=0x12341234
ldr r1,hexstring_addr
mov lr,pc
bx r1
;@ call a thumb function frm arm
ldr r0,=0x12312344
bl hexstring_trampoline
hang:
b hang
hexstring_trampoline:
ldr r1,hexstring_addr
bx r1
hexstring_addr: .word hexstring
Si nos fijamos en la referencia del conjunto de instrucciones se verá que es necesario utilizar BX o BLX para cambiar entre el brazo y el pulgar estados . BLX no es tan ampliamente compatible como BX.
Desde el punto de vista de la definición, el contador del programa, la PC tiene dos instrucciones por delante durante la ejecución de una instrucción. para el pulgar que es de 4 bytes, para armar 8 bytes. En cualquier caso, dos instrucciones. Para simular un bl que no se puede usar para cambiar el estado, debe cargar el registro de enlace con la dirección de retorno, y usar un bx para bifurcar al estado de cambio de función dependiendo del lsbit de la dirección. por lo que el
mov lr,pc
bx r1
here:
lr mov, PC por encima de carga la dirección de aquí: que es nuestra dirección de retorno, r1 bx de una manera independiente del estado llama a la función. el bit menos significativo de la dirección de izquierda a derecha indica el modo de volver a y hay que utilizar siempre BX para volver
pre_thumb:
ldr pc,lr
thumb_capable:
bx lr
El compilador asigna una instrucción de BL para llamar funciones, el enlazador rellena el resto más tarde, si es demasiado lejos de un alcance, entonces necesita una función de trampolín que el enlazador se está agregando. Del mismo modo, si necesita cambiar los modos, el bl llama a una función de trampolín que hace eso. He modelado eso en uno de los anteriores para imitar eso, se puede ver que es un poco derrochador, con suerte mi explicación del compilador solo asignando espacio para un bl lo hace más claro, desperdiciador sería siempre planear un cambio de modo y tiene que insertar nops para la mayoría de las llamadas a funciones en el código.
El código también incluye una llamada para armar desde el pulgar en ensamblador:
.thumb
.thumb_func
.globl XPUT32
XPUT32:
push {lr}
;@ call an arm function from thumb asm
ldr r2,=PUT32
mov lr,pc
bx r2
pop {r2}
bx r2
sobre todo igual, excepto que no se puede hacer estallar a LR en el modo de pulgar, que puede hacer estallar a la PC, pero yo no creo que cambia de modo , por lo que no puede usarlo, nuevamente necesita un registro extra. Usted, por supuesto, necesita saber las convenciones de llamada para saber qué registros se puede utilizar o se puede envolver otra serie de empujones y pops para preservar todos menos lr
push {r2,lr}
;@ call an arm function from thumb asm
ldr r2,=PUT32
mov lr,pc
bx r2
pop {r2}
mov lr,r2
pop {r2}
bx lr
pulgar a pulgar o un brazo a otro sólo tiene que utilizar un bl si puedes alcanzar ldr pc, dirección si no puedes.
dónde está el compilador? –
kernel.o :(. ARM.exidx + 0x0): referencia indefinida a '__aeabi_unwind_cpp_pr1 ' make: *** [kernel.elf] Error 1 –
¿Estás intentando construir una aplicación de brazo linux? o una aplicación incrustada (sin sistema operativo)? si es una aplicación de Linux, entonces no necesita el código de inicio, la cadena de herramientas debe hacer todo eso por usted, le preocupa que main() sea su punto de entrada. –