2014-02-23 4 views
1

엄지 손가락 인 Cortex-M3에서는 PC에 쓸 때마다 대상 주소 LSB가 '1'인지 확인하여 프로세서를 확실히 유지해야합니다 엄지 손가락 모드.Cortex-M3 (엄지 손가락)의 B 명령어 사용

또한 'BX reg'를 사용할 때 엄지 모드를 사용하려면 reg 값에 LSB = 1이 있어야합니다.

피질 -m3에서 'B 라벨'을 사용하는 경우는 어떨까요? 이 'label'은 16 비트/32 비트 명령어가 짝수 어드레스에 정렬되기 때문에 LSB = 0 인 값을 갖습니다. 'B label'이 'PC : = label'과 동일하지 않습니까?

PC 작성이 프로세서 모드에 영향을주지 않는 예외적 인 경우 'B 라벨'및 'BL 라벨'입니까?

감사합니다.

답변

1

대상 주소에 bx (및 blx) 명령어에 대해 lsbit a 1이 있어야하며, pc에 들어갈 때 1이 제거됩니다. b 명령은 pc 상대이며 arm 문서에 표시된 수학은 짝수임을 분명히합니다.

일반적으로 도구가 자신의 업무를 수행하게하려면 언제든지 걱정할 필요가 없습니다.

주는 다음

.thumb 

.globl _start 
_start: 
    b reset 
    nop 
    nop 
.thumb_func 
reset: 
    nop 
    nop 
    nop 
    nop 
    ldr r0,=reset 
    bx r0 

arm-none-eabi-as thumb.s -o thumb.o 
arm-none-eabi-ld -Ttext=0x1000 thumb.o -o thumb.elf 
arm-none-eabi-objdump -D thumb.elf 

thumb.s

thumb.elf:  file format elf32-littlearm 


Disassembly of section .text: 

00001000 <_start>: 
    1000: e001  b.n 1006 <reset> 
    1002: 46c0  nop   ; (mov r8, r8) 
    1004: 46c0  nop   ; (mov r8, r8) 

00001006 <reset>: 
    1006: 46c0  nop   ; (mov r8, r8) 
    1008: 46c0  nop   ; (mov r8, r8) 
    100a: 46c0  nop   ; (mov r8, r8) 
    100c: 46c0  nop   ; (mov r8, r8) 
    100e: 4801  ldr r0, [pc, #4] ; (1014 <reset+0xe>) 
    1010: 4700  bx r0 
    1012: 10070000 andne r0, r7, r0 
    ... 

분기는

1000: e001  b.n 1006 <reset> 
...  
00001006 <reset>: 
자체 돌봐

브랜치의 인코딩은 16 비트 단위로 바이트 단위가 아니며 단위를 2로 곱한 다음 (항상 시프트) 바이트 단위로 항상 짝수가됩니다. PC는 결코 이상하지 않습니다, 그것은 여러분이 bx 나 blx를 공급하는 값이 이상합니다.

리셋 전에 .thumb_func를 사용했기 때문에 어셈블러에 말하면 이것은 팔 레이블이 아닌 엄지 레이블입니다. 그래서 내가 r0에 리셋 된 주소를로드 할 때 어셈블러가 디스 어셈블리에서 이상한 것을 나타내는 값 0x00001007에 대한 데이터를 할당했지만 거기에 있습니다.당신이 .thumb_func

100c: 46c0  nop   ; (mov r8, r8) 
100e: 4801  ldr r0, [pc, #4] ; (1014 <reset+0xe>) 
1010: 4700  bx r0 
1012: 10060000 andne r0, r6, r0 
을 제거한다면 그들은 지금 우리

00001006 <reset>: 
... 
    100e: 4801  ldr r0, [pc, #4] ; (1014 <reset+0xe>) 
    1010: 4700  bx r0 
    1012: 10070000 andne r0, r7, r0 

에 대한 lsbit을 설정 한

어셈블러가 팔 주소 생각하고 lsbit를 설정하지 않고이 코드가 충돌 할 . 지금 당신이 그것에 관하여 염려하는 경우에 당신은 항상 추가 orr r0, # 1를 추가 할 수있다 그러나 진짜로 다만 전세 마차이다. 라벨을 팔이 아닌 엄지 손가락으로 선언하는 방법을 사용하는 어셈블러에 대해 알아보십시오. 그렇습니다. gnu 어셈블러가이 코드 세그먼트가 엄지 손가락이라는 것을 알고있는 것은 어리석은 것처럼 보입니다. 우리가 아직 말하지 않았기 때문에 엄지 코드 내의 레이블은 엄지 손가락 라벨입니다. 아주 바보 같은 도구.

그리고 나는이 함수 나 엄지 손가락 레이블 등을 선언 할 수있는 다른 자세한 GNU 어셈블러 지시문이 있다고 가정합니다. 그리고 물론 모든 어셈블러가 다르므로 gnu 어셈블러 지시문이 다른 어셈블러 지시문에서 작동한다고 가정하지 마십시오.

C와 asm을 섞으면 C 컴파일러는 바보가 아니며 -mthumb이 모든 함수와 전역 변수 (레이블)를 만들고 코드에서 사용하는 방법과 위치에 따라 링커에서 올바른 값을 배치한다는 것을 알고 있습니다. 그것은 심지어 지금까지 모드를 바꿀 수있는만큼 멀리 이동할 수 있습니다. bl 코드 코드는 main 코드를 사용하고, 모드를 전환하는 코드에는 trampoline 코드를 넣습니다. 또는 그 반대, 적어도 도구를 참조하십시오 (그리고 스택 오버플로 답변에서 여러 번 시연). 작동하지 않게하려면 까다로운 일임을 기억하지 못합니다. 그렇지 않으면 항상 주기적으로 해체해야하고 그렇지 않으면 링커가이 작업을 수행하도록 보장해야합니다. 그렇지 않으면 작업을 직접 수행하거나 항상 스스로 작업을 수행 할 수 있습니다.

그렇게

는 BX 및 BLX 엄지 손가락의 lsbit 세트를 필요로하고 두 lsbits가 무장 분파 다시 기억하십시오. blx 및 bx 명령은 lsbit을 제거하고 PC에 짝수 번호의 PC를 남깁니다 (매우 간단하게 mov r0, pc를 수행 한 다음 엄지 손가락 코드로 봅니다).

무조건 조건부 브랜치 (bx가 아님)는 절대로 팔을 엄지로, 엄지를 엄지로 전환해서는 안됩니다. bl과 동일하지만 gnu 도구가 도움이되는 것을 보았습니다. 코드를 순수하게 만들고 싶다면 도구가 올바르게 수행해야하는 레지스터에 주소를로드해야합니다. 그렇지 않으면 전체 도구 체인이 실패하고 bl 대신 blx가됩니다. 그 라벨은 당신을 위해 트램펄린을하는 툴체인에 의존하지 않습니다.

1

'B 라벨'은 'PC : = 라벨'과 동일하지 않습니까?

오프셋은 실제로 명령에서 인코딩되어 PC := PC + offset * 2입니다. 어셈블러/링커는이 오프셋을 계산해야합니다.

명령어 인코딩에 대한 자세한 내용은 Armv7-M 용 ARM 아키텍처 참조 문서를 참조하십시오.

PC 작성이 프로세서 모드에 영향을주지 않는 예외적 인 경우 'B 라벨'및 'BL 라벨'입니까?

예. 마지막 비트는 이 아니며 B(L) label 명령어로 인코딩 된이 아니므로 엄지 모드 비트를 변경할 수 없습니다.