vedere la directory http://github.com/dwelch67/yagbat qemu.
Ecco un paio di esempi di chiamare il braccio o il pollice dal braccio
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
Se si guarda il riferimento set di istruzioni vedrete che è necessario utilizzare BX o BLX per passare tra braccio e pollice stati . BLX non è ampiamente supportato come BX.
Dal punto di vista della definizione, il contatore del programma, pc è due istruzioni successive durante l'esecuzione di un'istruzione. per pollice che è 4 byte, per braccio 8 byte. In entrambi i casi due istruzioni. Per simulare un bl che non può essere usato per cambiare stato, è necessario caricare il registro di collegamento con l'indirizzo di ritorno, e utilizzare un bx per diramarlo allo stato di modifica della funzione a seconda dell'lbit dell'indirizzo. così il
mov lr,pc
bx r1
here:
lr converter, pc sopra carica l'indirizzo di qui: che è il nostro indirizzo di ritorno, bx r1 in modo indipendente stato chiama la funzione. la LSBit dell'indirizzo lr indica il modo per tornare a ed è necessario utilizzare sempre BX per tornare
pre_thumb:
ldr pc,lr
thumb_capable:
bx lr
Il compilatore alloca un'istruzione bl per le funzioni di chiamata, il linker riempie il resto più tardi, se è troppo di gran lunga quindi ha bisogno di una funzione trampolino che il linker si aggiunge. Allo stesso modo, se è necessario cambiare modalità, il bl chiama una funzione trampolino che lo fa. Ho modellato che in uno dei precedenti per simularlo, si può vedere che è un po 'dispendioso, si spera che la mia spiegazione del compilatore che alloca solo lo spazio per un bl rende più chiaro e dispendioso pianificare sempre un cambio di modalità e inserire nops per la maggior parte delle chiamate di funzione nel codice.
Il codice comprende anche una chiamata a braccio dal pollice in assembler:
.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
per lo più lo stesso, tranne non si può pop alla Lr in modalità pollice, è possibile pop al pc, ma non penso che gli interruttori modalità , quindi non puoi usarlo, hai ancora bisogno di un registro di riserva. È ovviamente necessario conoscere le convenzioni di chiamata per sapere cosa registri è possibile utilizzare o si può avvolgere un altro set di spinte e pop per conservare tutti, ma 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
pollice per pollice o un braccio all'altro è sufficiente utilizzare un bl se puoi raggiungere pc ldr, indirizzo se non puoi.
dove si trova questo compilatore da? –
kernel.o :(. ARM.exidx + 0x0): riferimento non definito a '__aeabi_unwind_cpp_pr1 ' make: *** [kernel.elf] Errore 1 –
stai provando a creare un'applicazione arm linux? o un'applicazione incorporata (senza sistema operativo)? se un'applicazione Linux non ha bisogno di codice di avvio, la toolchain dovrebbe fare tutto questo per te, ti preoccupi di main() come punto di ingresso. –