Я предполагаю, что вы имеете в виду межсетевое взаимодействие, а не межсетевое взаимодействие? LPC1769 — это cortex-m3, работающий только с большим пальцем/большим пальцем2, поэтому он не поддерживает инструкции руки, поэтому для этой платформы нет возможности взаимодействия. Тем не менее, играя с компилятором, чтобы увидеть, что происходит:
Сначала заставьте компилятор сделать это за вас, а затем попробуйте сами на ассемблере...
старт.с
.thumb
.globl _start
_start:
ldr r0,=hello
mov lr,pc
bx r0
hang : b hang
Привет
extern unsigned int two ( unsigned int );
unsigned int hello ( unsigned int h )
{
return(two(h)+7);
}
два.с
unsigned int two ( unsigned int t )
{
return(t+5);
}
Makefile
hello.list : start.s hello.c two.c
arm-none-eabi-as -mthumb start.s -o start.o
arm-none-eabi-gcc -c -O2 hello.c -o hello.o
arm-none-eabi-gcc -c -O2 -mthumb two.c -o two.o
arm-none-eabi-ld -Ttext=0x1000 start.o hello.o two.o -o hello.elf
arm-none-eabi-objdump -D hello.elf > hello.list
clean :
rm -f *.o
rm -f *.elf
rm -f *.list
производит hello.list
Disassembly of section .text:
00001000 <_start>:
1000: 4801 ldr r0, [pc, #4] ; (1008 <hang+0x2>)
1002: 46fe mov lr, pc
1004: 4700 bx r0
00001006 <hang>:
1006: e7fe b.n 1006 <hang>
1008: 0000100c andeq r1, r0, ip
0000100c <hello>:
100c: e92d4008 push {r3, lr}
1010: eb000004 bl 1028 <__two_from_arm>
1014: e8bd4008 pop {r3, lr}
1018: e2800007 add r0, r0, #7
101c: e12fff1e bx lr
00001020 <two>:
1020: 3005 adds r0, #5
1022: 4770 bx lr
1024: 0000 movs r0, r0
...
00001028 <__two_from_arm>:
1028: e59fc000 ldr ip, [pc] ; 1030 <__two_from_arm+0x8>
102c: e12fff1c bx ip
1030: 00001021 andeq r1, r0, r1, lsr #32
1034: 00000000 andeq r0, r0, r0
hello.o разобрал сам:
00000000 <hello>:
0: e92d4008 push {r3, lr}
4: ebfffffe bl 0 <two>
8: e8bd4008 pop {r3, lr}
c: e2800007 add r0, r0, #7
10: e12fff1e bx lr
компилятор использует bl, предполагая/надеясь, что он будет вызывать руку из руки. но этого не произошло, поэтому они поставили туда батут.
0000100c <hello>:
100c: e92d4008 push {r3, lr}
1010: eb000004 bl 1028 <__two_from_arm>
1014: e8bd4008 pop {r3, lr}
1018: e2800007 add r0, r0, #7
101c: e12fff1e bx lr
00001028 <__two_from_arm>:
1028: e59fc000 ldr ip, [pc] ; 1030 <__two_from_arm+0x8>
102c: e12fff1c bx ip
1030: 00001021 andeq r1, r0, r1, lsr #32
1034: 00000000 andeq r0, r0, r0
bl to __two_from_arm — это ответвленная ссылка между режимами постановки на охрану. адрес функции назначения (два) с установленным lsbit, который указывает bx переключиться в режим большого пальца, загружается в одноразовый регистр ip (r12?), затем происходит переключение режимов ip bx. ссылка ответвления установила обратный адрес в lr, который, без сомнения, был адресом режима охраны (нулевой lsbit).
00001020 <two>:
1020: 3005 adds r0, #5
1022: 4770 bx lr
1024: 0000 movs r0, r0
функция two() делает свое дело и возвращает результат, обратите внимание, что при взаимодействии вы должны использовать bx lr, а не mov pc,lr. По сути, если вы не используете ARMv4 без T или ARMv5 без T, mov pc,lr — это нормальная привычка. Но любой ARMv4T или новее (ARMv5T или новее) использует bx lr для возврата из функции, если у вас нет особых причин не делать этого. (избегайте использования pop {pc} по той же причине, если вам действительно не нужно сохранять эту инструкцию и не взаимодействуете). Теперь, будучи на cortex-m3, который поддерживает только thumb+thumb2, вы не можете взаимодействовать, поэтому вы можете использовать mov pc,lr и pop {pc}, но код не переносим, и это не очень хорошая привычка, так как эта привычка укусит вас, когда вы вернетесь к программированию рук.
Итак, поскольку hello был в режиме arm, когда он использовал bl, который устанавливает регистр связи, bx в two_from_arm не касается регистра связи, поэтому, когда two() возвращается с bx lr, он возвращается в режим arm после bl __two_from_arm. строка в функции hello().
Также обратите внимание на дополнительный 0x0000 после функции большого пальца, это должно было выровнять программу по границе слова, чтобы следующий код руки был выровнен...
чтобы увидеть, как компилятор меняет два пальца на руку следующим образом
unsigned int three ( unsigned int );
unsigned int two ( unsigned int t )
{
return(three(t)+5);
}
и поместите эту функцию в hello.c
extern unsigned int two ( unsigned int );
unsigned int hello ( unsigned int h )
{
return(two(h)+7);
}
unsigned int three ( unsigned int t )
{
return(t+3);
}
и теперь у нас есть еще один батут
00001028 <two>:
1028: b508 push {r3, lr}
102a: f000 f80b bl 1044 <__three_from_thumb>
102e: 3005 adds r0, #5
1030: bc08 pop {r3}
1032: bc02 pop {r1}
1034: 4708 bx r1
1036: 46c0 nop ; (mov r8, r8)
...
00001044 <__three_from_thumb>:
1044: 4778 bx pc
1046: 46c0 nop ; (mov r8, r8)
1048: eafffff4 b 1020 <three>
104c: 00000000 andeq r0, r0, r0
Теперь это очень крутой батут. bl to three_from_thumb находится в режиме большого пальца, а регистр связи настроен на возврат к функции two() с установленным lsbit, без сомнения, для указания возврата в режим большого пальца.
Батут начинается с bx pc, pc настроен на две инструкции вперед, а внутри pc всегда очищен lsbit, поэтому bx pc всегда переводит вас в режим постановки на охрану, если он еще не находится в режиме постановки на охрану, и в любом режиме на две инструкции вперед. Две инструкции перед bx pc — это инструкция руки, которая разветвляется (не разветвляется!) на три функции, завершая батут.
Обратите внимание, как я написал вызов hello() в первую очередь
_start:
ldr r0,=hello
mov lr,pc
bx r0
hang : b hang
это на самом деле не будет работать не так ли? Он перенесет вас из руки в большой палец, но не из большого пальца в руку. Я оставлю это в качестве упражнения для читателя.
Если вы измените start.s на это
.thumb
.globl _start
_start:
bl hello
hang : b hang
компоновщик заботится о нас:
00001000 <_start>:
1000: f000 f820 bl 1044 <__hello_from_thumb>
00001004 <hang>:
1004: e7fe b.n 1004 <hang>
...
00001044 <__hello_from_thumb>:
1044: 4778 bx pc
1046: 46c0 nop ; (mov r8, r8)
1048: eaffffee b 1008 <hello>
Я бы всегда дизассемблировал подобные программы, чтобы убедиться, что компилятор и компоновщик решили эти проблемы. Также обратите внимание, что, например, __hello_from_thumb можно использовать из любой функции thumb, если я вызываю hello из нескольких мест, какая-то рука, какой-то большой палец, и hello был скомпилирован для руки, тогда вызовы руки будут вызывать hello напрямую (если они могут до него добраться) и все вызовы большого пальца будут использовать один и тот же hello_from_thumb (если они смогут его достичь).
Компилятор в этих примерах предполагал, что код остается в том же режиме (простая ссылка на ветку), а компоновщик добавил код взаимодействия...
Если вы действительно имели в виду межсетевое взаимодействие, а не межсетевое взаимодействие, то, пожалуйста, опишите, что это такое, и я удалю этот ответ.
РЕДАКТИРОВАТЬ:
Вы использовали регистр для сохранения lr во время вызова Double, это не сработает, никакой регистр не сработает, для этого нужно использовать память, а проще всего — стек. Посмотрите, как это делает компилятор:
00001008 <hello>:
1008: e92d4008 push {r3, lr}
100c: eb000009 bl 1038 <__two_from_arm>
1010: e8bd4008 pop {r3, lr}
1014: e2800007 add r0, r0, #7
1018: e12fff1e bx lr
r3, скорее всего, выровняет стек по 64-битной границе (делает его быстрее). следует отметить, что регистр ссылки сохраняется в стеке, но всплывающее окно не извлекается на компьютер, потому что это не сборка ARMv4, поэтому для возврата из функции требуется bx. Поскольку это режим постановки на охрану, мы можем перейти к lr и просто bx lr.
Для большого пальца вы можете нажимать только r0-r7 и lr напрямую и выталкивать r0-r7 и pc напрямую, вы не хотите выталкивать на pc, потому что это работает, только если вы остаетесь в том же режиме (большой палец или рука). это хорошо для cortex-m, или хорошо, если вы знаете, что такое все ваши абоненты, но в целом плохо. Так
00001024 <two>:
1024: b508 push {r3, lr}
1026: f000 f811 bl 104c <__three_from_thumb>
102a: 3005 adds r0, #5
102c: bc08 pop {r3}
102e: bc02 pop {r1}
1030: 4708 bx r1
та же сделка r3 используется в качестве фиктивного регистра, чтобы поддерживать стек в выравнивании для повышения производительности (я использовал сборку по умолчанию для gcc 4.8.0, которая, вероятно, является платформой с 64-битной аксиальной шиной, указав, что архитектура может удалить этот дополнительный регистр). Поскольку мы не можем вытолкнуть pc, я предполагаю, что из-за того, что r1 и r3 были бы не в порядке, и был выбран r3 (они могли выбрать r2 и сохранить инструкцию), есть два выталкивания, одно, чтобы избавиться от фиктивного значения в стеке, и другой, чтобы поместить возвращаемое значение в регистр, чтобы они могли вернуться к нему.
Ваша функция Start не соответствует ABI, и в результате, когда вы смешиваете ее с такими большими библиотеками, как вызов printf, вы, без сомнения, выйдете из строя. Если вы этого не сделали, это была глупая удача. Ваш ассемблерный список main показывает, что ни r4, ни r10 не использовались, и если предположить, что main() не вызывается, кроме начальной загрузки, то именно поэтому вам сошло с рук либо r4, либо r10.
Если это действительно LPC1769, то все это обсуждение не имеет значения, так как он не поддерживает ARM и не поддерживает взаимодействие (взаимодействие = смешение кода режима ARM и кода режима большого пальца). Ваша проблема не была связана с межсетевым взаимодействием, вы не взаимодействуете (обратите внимание на поп {pc} в конце функций). Ваша проблема, вероятно, была связана с вашим ассемблерным кодом.
РЕДАКТИРОВАТЬ2:
Изменение make-файла для указания cortex-m
00001008 <hello>:
1008: b508 push {r3, lr}
100a: f000 f805 bl 1018 <two>
100e: 3007 adds r0, #7
1010: bd08 pop {r3, pc}
1012: 46c0 nop ; (mov r8, r8)
00001014 <three>:
1014: 3003 adds r0, #3
1016: 4770 bx lr
00001018 <two>:
1018: b508 push {r3, lr}
101a: f7ff fffb bl 1014 <three>
101e: 3005 adds r0, #5
1020: bd08 pop {r3, pc}
1022: 46c0 nop ; (mov r8, r8)
во-первых, это все большой палец, поскольку на cortex-m нет режима руки, во-вторых, bx не требуется для возврата функции (поскольку нет изменений режима руки / большого пальца). Так что pop {pc} будет работать.
Любопытно, что фиктивный регистр все еще используется при отправке, я пробовал сборку arm7tdmi/armv4t, и она все еще работала, поэтому есть какой-то другой флаг, который можно использовать, чтобы избавиться от этого поведения.
Если бы вы хотели узнать, как создать функцию на ассемблере, которую можно было бы вызывать из C, вы должны были это сделать. Создайте функцию C, которая чем-то напоминает структуру функции, которую вы хотите создать на ассемблере:
extern unsigned int Double ( unsigned int );
unsigned int Start ( void )
{
return(Double(42));
}
собрать потом разобрать
00000000 <Start>:
0: b508 push {r3, lr}
2: 202a movs r0, #42 ; 0x2a
4: f7ff fffe bl 0 <Double>
8: bd08 pop {r3, pc}
a: 46c0 nop ; (mov r8, r8)
и начните с того, что вы выполняете функцию сборки.
.globl Start
.thumb_func
Start:
push {lr}
mov r0, #42
bl Double
pop {pc}
То, или прочитать arm abi для gcc и понять какие регистры можно и нельзя использовать не сохраняя их в стеке, какие регистры используются для передачи и возврата параметров.
person
old_timer
schedule
21.04.2013
Double(7);
в вашем main()? - person ott--   schedule 21.04.2013