см. http://github.com/dwelch67/yagbat каталог qemu.
Вот несколько примеров вызова руки или большого пальца из руки
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
Если вы посмотрите на справочник по набору команд, вы увидите, что вам нужно использовать BX или BLX для переключения между состояниями руки и большого пальца. BLX не так широко поддерживается, как BX.
С точки зрения определения, программный счетчик pc на две команды впереди во время выполнения инструкции. для большого пальца 4 байта, для плеча 8 байтов. В любом случае две инструкции. Чтобы смоделировать bl, который нельзя использовать для изменения состояния, вам нужно загрузить регистр связи с обратным адресом и использовать bx для перехода к состоянию изменения функции в зависимости от lsbit адреса. так что
mov lr,pc
bx r1
here:
mov lr, pc выше загружает адрес здесь: это наш обратный адрес, bx r1 независимо от состояния вызывает функцию. lsbit lr-адреса указывает режим возврата, и вам всегда нужно использовать bx для возврата
pre_thumb:
ldr pc,lr
thumb_capable:
bx lr
Компилятор выделяет инструкцию bl для вызова функций, а компоновщик заполняет остальные позже, если он слишком далеко, то ему нужна функция батута, которую компоновщик добавляет сам. Аналогичным образом, если вам нужно изменить режимы, BL вызывает функцию батута, которая делает это. Я смоделировал, что в одном из вышеперечисленного имитировать это, вы можете видеть, что это немного расточительно, надеюсь, мое объяснение того, что компилятор только выделяет место для bl, делает более ясным, расточительным было бы всегда планировать изменение режима и необходимо вставить nops для большинства вызовов функций в коде.
Код также включает в себя вызов на руку с большого пальца в ассемблере:
.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
в основном то же самое, за исключением того, что вы не можете получить доступ к lr в режиме большого пальца, вы можете получить доступ к компьютеру, но я не думаю, что переключает режимы, поэтому вы не можете его использовать, вам снова нужен запасной регистр. Конечно, вам нужно знать соглашения о вызовах, чтобы знать, какие регистры вы можете использовать, или вы можете обернуть другой набор толчков и всплывающих окон, чтобы сохранить все, кроме 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
Большой палец к большому или рука к руке, просто используйте bl, если можете достать. Ldr ПК, адрес, если вы не можете.