Arm 어셈블리 학습 노트(9) - 효율적인 분기 코드 및 비정합 데이터 접근
4867 단어 ARM 어셈블리
1. 0 <=x < N 유형의 분기 코드
이 경우 N은 다음 C 코드의 경우 크게 사용할 수 없습니다.
4
int ref_switch(int x)
{
switch (x) {
case 0: return method_0();
case 1: return method_1();
case 2: return method_2();
case 3: return method_3();
case 4: return method_4();
case 5: return method_5();
case 6: return method_6();
case 7: return method_7();
default: return method_d();
}
}
우리는 pc레지스터의 값을 기준으로 x의 값을 인덱스로 실현할 수 있다. 최적화된 어셈블리 코드는 다음과 같다. ; int switch_relative(int x)
switch_relative
MP x, #8
ADDLT pc, pc, x, LSL#2
B method_d
B method_0
B method_1
B method_2
B method_3
B method_4
B method_5
B method_6
B method_7
2.x는 일반적인 값이다
만약 x가 0<=x
다음은 최적화된 어셈블리 코드입니다.
x RN0
hash RN 1
; int switch_hash(int x)
switch_hash
RSB hash, x, x, LSL#4 ; hash=x*15
RSB hash, hash, hash, LSL#5 ; hash=x*15*31
AND hash, hash, #7 << 9 ; mask out the hash value
ADD pc, pc, hash, LSR#6
NOP
TEQ x, #0x01
BEQ method_0
TEQ x, #0x02
BEQ method_1
TEQ x, #0x40
BEQ method_6
TEQ x, #0x04
BEQ method_2
TEQ x, #0x80
BEQ method_7
TEQ x, #0x20
BEQ method_5
TEQ x, #0x10
BEQ method_4
TEQ x, #0x08
BEQ method_3
B method_d
위의 방법은 우리가 제시한 특례일 뿐이다. x가 2가 아닌 멱인 상황에서 우리는 여전히 비슷한 방법을 사용하여 실현할 수 있다.여기에는 단지 하나의 사고방식을 제공할 뿐이다.
3. 정렬되지 않은 데이터 액세스
주소가 맞지 않는 데이터 접근은 가능한 한 피해야 한다. 그렇지 않으면 이식 가능성과 효율에 불리하다.
4
다음 코드는 주소가 맞지 않는 32비트 데이터를 읽습니다. 우리는 t0, t1, t2 세 개의 레지스터를 사용하여 유수선이 서로 잠기지 않도록 읽습니다.ARM9TDMI에서 주소가 아닌 각 데이터를 읽으려면 7 개의 클럭 주기가 필요합니다.다음 예에서littleendian 및 bigendian에 대응하는 버전입니다.
p RN0 x RN1
t0 RN 2
t1 RN 3
t2 RN 12
; int load_32_little(char *p)
load_32_little
LDRB x, [p]
LDRB t0, [p, #1]
LDRB t1, [p, #2]
LDRB t2, [p, #3]
ORR x, x, t0, LSL#8
ORR x, x, t1, LSL#16
ORR r0, x, t2, LSL#24
MOV pc, lr
; int load_32_big(char *p)
load_32_big
LDRB x, [p]
LDRB t0, [p, #1]
LDRB t1, [p, #2]
LDRB t2, [p, #3]
ORR x, t0, x, LSL#8
ORR x, t1, x, LSL#8
ORR r0, t2, x, LSL#8
MOV pc, lr
; void store_32_little(char *p, int x)
store_32_little
STRB x, [p]
MOV t0, x, LSR#8
STRB t0, [p, #1]
MOV t0, x, LSR#16
STRB t0, [p, #2]
MOV t0, x, LSR#24
STRB t0, [p, #3]
MOV pc, lr
; void store_32_big(char *p, int x)
store_32_big
MOV t0, x, LSR#24
STRB t0, [p]
MOV t0, x, LSR#16
STRB t0, [p, #1]
MOV t0, x, LSR#8
STRB t0, [p, #2]
STRB x, [p, #3]
MOV pc,lr