2016-10-29 12 views
0

필요한 상수 값 : 행AVR의 GCC 어셈블리 C 스텁 함수 EOR 및이 코드에 봉착

uint16_t swap_bytes(uint16_t x) 
{ 
    asm volatile(
     "eor, %A0, %B0"  "\n\t" 
     "eor, %B0, %A0"  "\n\t" 
     "eor, %A0, %B0"  "\n\t" 
     : "=r" (x) 
     : "0" (x) 
    ); 
    return x; 
} 

변환 (avr- gcc version 4.8.1 의해 -std=gnu99 -save-temps로를)

.global swap_bytes 
    .type swap_bytes, @function 
swap_bytes: 
/* prologue: function */ 
/* frame size = 0 */ 
/* stack size = 0 */ 
.L__stack_usage = 0 
/* #APP */ 
; 43 "..\lib\own\ownlib.c" 1 
    eor, r24, r25 
    eor, r25, r24 
    eor, r24, r25 

; 0 "" 2 
/* #NOAPP */ 
    ret 
    .size swap_bytes, .-swap_bytes 

그렇다면 컴파일러는 다음과 같은 불평을합니다.

|65|Error: constant value required| 
|65|Error: garbage at end of line| 
|66|Error: constant value required| 
|66|Error: garbage at end of line| 
|67|Error: constant value required| 
|67|Error: garbage at end of line| 
||=== Build failed: 6 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| 

eor 명령을 사용하십시오. 왜 컴파일러가 문제가 있습니까? 레지스터는 거의 모든 연산이 가능한 상위 (> = r16) 레지스터입니다. constant value required 그것이 리터럴을 기대하는 것처럼 나에게 소리가 난다. 나는 그것을 얻지 않는다.

+0

gcc에는 gcc가 내장되어 있습니다. 왜 그걸 사용하지 않니? 어쨌든 컴파일러에 의존합니다. 왜 plain C를 사용하지 않습니까? – Olaf

+0

나는 올라프와있다 : 가능한 경우 내장 된 것을 사용하라. 그러나 반드시 인라인 asm을 사용해야한다면 문제가 "여분"쉼표인지 궁금합니다. 인터넷 검색은 'r4, r4'및 'eor r0, r22'로 표시됩니다 (eor 명령 다음에 쉼표가 없음). 나는 전문가는 아니지만 그게 내가 먼저 해보려는 것입니다. –

+0

f # * k! 네가 옳아. 거기에는','가 없어야합니다. 어쨌든 AVR은 마이크로 컨트롤러이므로 프로그램 공간이 부족합니다. 3 인스트럭션은 C에게 탁월합니다. 다시 여러분 께 감사드립니다! – milkpirate

답변

0

그냥 미래 Google 직원 명확히 :

eor, r24, r25 

는 EOR 후 여분의 쉼표가 있습니다.

eor r24, r25 

나는 또한 당신을 격려 할가 (다시) GCC의 __builtin_bswap16 사용을 고려하는이 ​​다음과 같이 작성해야한다. gcc 'builtin'함수에 익숙하지 않은 경우 컴파일러에 내장 된 함수이며 (함수처럼 보이지만) 일반적으로 인라인됩니다. 그들은 다양한 프로세서의 모든 기능을 이해하고 고려하지 않은 사항을 고려할 수있는 사람들이 작성하고 최적화했습니다.

코드를 최대한 작게 유지하고자합니다. 그리고 나는 (어쨌든) 당신의 특정 프로세서에 내장 된이 코드가 차선책 코드를 생성 할 가능성이 있음을 인정합니다. 반면에, 그것은 정확히 같은 코드를 생성 할 수 있습니다. 또는이 작업을 수행하는 데 더 영리한 트릭을 사용할 수도 있습니다. 또는 파이프 라이닝 (또는 내가 'avr'을 말하지 않기 때문에 들어 본 적이없는 다른 avr 특정 사항)을 이용하기 위해 주변 코드의 명령어를 인터리브 할 수 있습니다.

무엇보다,이 코드를 고려하십시오

int main() 
{ 
    return __builtin_bswap16(12345); 
} 

코드는 항상 스왑을 처리하기 위해 3 개 지시합니다. 그러나 내장 함수를 사용하면 컴파일러는 arg가 일정하다는 것을 인식하고 런타임이 아닌 컴파일 타임에 값을 계산할 수 있습니다. 그것보다 더 효율적이지는 않습니다.

나는 "지원하기 쉽다"라는 이점을 지적 할 수도 있습니다. 인라인 asm을 작성하는 것은 올바르게 수행하는 것이 어렵습니다. 그리고 미래의 메인테이너들은 어떻게 작동하는지 결코 확신 할 수 없으므로 그것을 만지는 것을 싫어합니다. 물론 내장 된 플랫폼은 더 많은 플랫폼을 지원할 수 있습니다.

아직도 확신하지 못 하셨나요? 내 마지막 피치 : 쉼표를 수정 한 후에도 인라인 asm 코드는 여전히 적절하지 않습니다. 때문에 두 번, GCC는 값을 계산한다 (즉, volatile 사용) 작성 swap_bytes를 쓴 방법 (volatile의 정의 참조)의

int main(int argc, char *argv[]) 
{ 
    return swap_bytes(argc) + swap_bytes(argc); 
} 

:이 코드를 생각해 보자. 휘발성을 생략했다면 (또는 이것을 올바르게 수행하는 내장 함수를 사용했다면) argc가 첫 번째 호출의 출력을 변경하고 다시 사용하지 않는다는 것을 알았을 것입니다. 인라인 asm을 올바르게 쓰는 것이 어렵다는 것을 언급 했습니까?

코드, 제약 조건, 전문 지식 또는 요구 사항을 알지 못합니다. 어쩌면 당신의 솔루션이 정말로 최고 일 것입니다. 내가 할 수있는 일은 생산 코드에서 인라인 asm을 사용하기 전에 당신이 길고 힘차게 생각하도록 격려하는 것입니다.