2017-12-27 41 views
0

난과 같이 인라인 어셈블리를 사용하여 C에서 동작 왼쪽 회전을 작성하려고하고 회전 :인라인 어셈블리 크기 불일치

(바이트 부호없는 문자로 typedefed된다)
byte rotate_left(byte a) { 
    __asm__("rol %0, $1": "=a" (a) : "a" (a)); 
    return a; 
} 

.

이 오류 문제가 여기에 무엇

/tmp/ccKYcEHR.s:363: Error: operand size mismatch for `rol'.

제기?

+1

여기서 '바이트'를 정의합니까? – klutt

+0

AT & T 구문을 사용하면 src와 대상이 반대입니다. 아마도 "rol $ 1, % 0"' –

+1

https://godbolt.org/g/z6Qof7을 의미 할 수도 있습니다. (최소한 gcc와 clang은) –

답변

3

& T 구문은 인텔 구문과 반대 순서를 사용합니다. 회전 수는 마지막이 아닌 처음이어야합니다 (rol $1, %0).


또한, 당신이 필요로하지 않으며, 이에 대한 인라인 어셈블리를 사용하지 않아야합니다 : 회전 - 관용구 인식 코드가 실패하기 때문에 Best practices for circular shift (rotate) operations in C++에서 설명한 바와 같이 https://gcc.gnu.org/wiki/DontUseInlineAsm

, GNU C는 좁은 회전을위한 내장 함수가 있습니다 회전 수의 and을 최적화 할 수 있습니다. x86에서는 8 비트 및 16 비트의 경우에도 count & 31으로 마스크를 이동/회전하지만 회전은 계속됩니다. 그것은 교대로 중요합니다.

어쨌든 gcc에는 오버 헤드를 피하기 위해 좁은 회전을위한 내장 기능이 있습니다. x86intrin.h에는 __rolb 래퍼가 있지만 MSVC는 등의 intrin.h을 사용합니다. 어쨌든 clang은 회전을위한 __builtin 또는 x86intrin.h 래퍼를 지원하지 않지만 gcc와 ICC는 지원합니다.

#include <stdint.h> 
uint8_t rotate_left_byte_by1(uint8_t a) { 
    return __builtin_ia32_rolqi(a, 1); // qi = quarter-integer 
} 

은 내가 byte 유형을 정의하는 대신 정상적인 사람처럼 stdint.h에서 uint8_t을 사용했다.

이 전혀 그 소리와 함께 컴파일되지 않습니다,하지만 it compiles as you'd hope with gcc7.2 :

rotate_left_byte_by1: 
    movl %edi, %eax 
    rolb %al 
    ret 

이렇게하면 지금은 할 수 귀하의 인라인 어셈블리로 효율적으로 컴파일 기능을 제공하지만, 어느 것이 컴파일 시간을 완전히 최적화 할 수 있습니다 상수 및 컴파일러는 작동 방식/수행 방식을 알고 그에 따라 최적화 할 수 있습니다.

+0

gcc는 순진한 회전을 하나만 인식] (https://godbolt.org/g/z6Qof7), 내장 함수를 사용할 필요가없는 것 같습니다. 그러나 VC++와 icc가 모두 그것을 인식하지 못하는 것은 궁금합니다. –

+0

@MatteoItalia : 그것을 인식 합니다만 런타임 변수 수를 감추는'and'없이 'rolb'만 내보내는 것은 어렵습니다. 그리고 아마도 내장 명령은 이디엄 인식자가 바이트와 16 비트를 처리하기 전에 추가되었습니다. 나는 오래된 gcc 버전을 확인하지 않았다. –

+0

업데이트 : 자유롭게 uint8_t에 캐스트를 추가하면 VC++ [인식 함] (https://godbolt.org/g/fSn6YK) (왼쪽 시프트 중 하나만해도 문제가없는 것 같습니다). –