2010-06-24 3 views
2

새내기 ARM 어셈블러 질문. 내 첫 번째 팔 어셈블러 프로그램을 쓰고 있는데이 C 코드를 코딩하려고합니다.멀티 피치 후 암 어셈블러 오른쪽 시프트?

int x = somevalue1 << 12; // s19.12 

int y = somevalue2 << 12; // s19.12 

int a = somevalue3 << 12; // s19.12 

int b = somevalue4 << 12; // s19.12 

int c = somevalue4 << 12; // s19.12 

long long acc = (long long) a * b; 

acc += (long long) x * y; 

int res = (acc >> 24); 

acc += (long long) c * a; 

저는 첫 번째 부분을 코딩하고 r10, r11 레지스터에서 합계를 계산했습니다.

@ r6 =a, r4 = b, r0 = x,r2 =y, r3=c 

smull r10, r11, r6, r4 @acc = a * b 

smlal r10, r11, r0, r2 @acc += x * y 

이제 I은 24 비트에 의해 "긴 긴"이동 오른쪽으로 위로 R10 및 R11 레지스터에서 "입술"의 값을 추출 할 필요가있다. 어떻게해야합니까?

고마워요,

답변

3

R10은 하부 32 비트를 포함하고, R11는 상위 32 비트를 포함한다.

r10   r11 
0 1 2 3 4 5 6 7 

당신이 원하는 결과는 다음과 같습니다

r12 
3 4 5 6 

은 즉, 최종 결과는 R11의 낮은 24 비트 및 R10의 상위 8 비트를 포함 할 것이다. 부호없는 산술을 사용하면 비트를 추출하는 것이 간단합니다. 부호가있는 산술을 사용하고 있기 때문에 부호를 보존해야합니다. 또한 필요에 따라 long long을 정수로 변환하여 상위 8 비트를 삭제합니다.

먼저 r11의 하위 24 비트를 최종 위치로 이동해 봅시다. 산술 왼쪽 쉬프트는 부호가 유지되도록합니다.

mov r12, r11 asl #8 

이제이 비트를 r12의 적절한 위치에 삽입하십시오. 우리는 이미 부호가 상위 비트에 대해 정확하다는 것을 확인 했으므로 여기서 논리적 인 교대를 사용하십시오.

orr r12, r10 lsr #24 

위의이 C에 해당 :

r12 = ((signed)r11 << 8); 
r12 |= ((unsigned)r10 >> 24); 

당신은, 물론, 단지 컴파일러는 당신을 위해이 같은 코드를 생성하도록 할 수 있습니다. 컴파일러에서 C로 오랫동안 올바르게 이동하려면 다음을 사용해야합니다.

int res = (acc >> 24LL); 
+0

마지막 문장에서 정정하십시오. C의 정수 승격 규칙은 이진 연산자의 피연산자를 결코 좁히지 않습니다. '(acc >> 24)'에''acc'에 맞게''long long''으로 확장됩니다. –

+0

@Mike Seymour. 결정된. – jbarlow