문제

다음 어셈블러 경고를 제거하는 방법을 아는 사람이 있습니까?

코드는 x86, 32비트입니다.

int test (int x)
{
  int y;
  // do a bit-rotate by 8 on the lower word. leave upper word intact.
  asm ("rorw $8, %0\n\t": "=q"(y) :"0"(x));
  return y;
}

컴파일하면 다음과 같은 (매우 유효한) 경고가 표시됩니다.

Warning: using `%ax' instead of `%eax' due to `w' suffix

내가 찾고 있는 것은 컴파일러/어셈블러에게 %0의 하위 16비트 하위 레지스터에 액세스하고 싶다고 알리는 방법입니다.바이트 하위 레지스터(이 경우 AL 및 AH)에 액세스하는 것도 알아두면 좋을 것입니다.

나는 이미 "q" 수정자를 선택했기 때문에 컴파일러는 EAX, EBX, ECX 또는 EDX를 사용해야 합니다.컴파일러가 하위 레지스터가 있는 레지스터를 선택해야 한다는 것을 확인했습니다.

나는 asm 코드가 특정 레지스터(및 그 하위 레지스터)를 사용하도록 강제할 수 있다는 것을 알고 있지만 레지스터 할당 작업은 컴파일러에 맡기고 싶습니다.

도움이 되었습니까?

해결책

당신이 사용할 수있는 %w0 내 기억이 맞다면.저도 방금 테스트해봤습니다.:-)

int
test(int x)
{
    int y;
    asm ("rorw $8, %w0" : "=q" (y) : "0" (x));
    return y;
}

편집하다:OP에 대한 응답으로 예, 다음도 수행할 수 있습니다.

int
test(int x)
{
    int y;
    asm ("xchg %b0, %h0" : "=Q" (y) : "0" (x));
    return y;
}

현재, (내가 아는) 그것이 문서로 기록된 유일한 장소는 다음과 같습니다. gcc/config/i386/i386.md, 표준 문서에는 없습니다.

다른 팁

오래 전이지만 나중에 참고할 때 필요할 것 같습니다...

Chris의 훌륭한 답변에 추가하면 핵심은 '%'와 출력 피연산자 수 사이에 수정자를 사용하는 것입니다.예를 들어, "MOV %1, %0" 될 수도 있다 "MOV %q1, %w0".

Constraints.md에서는 아무것도 찾을 수 없었지만 /gcc/config/i386/i386.c 소스에 이 잠재적으로 유용한 설명이 있었습니다. print_reg():

/* Print the name of register X to FILE based on its machine mode and number.
   If CODE is 'w', pretend the mode is HImode.
   If CODE is 'b', pretend the mode is QImode.
   If CODE is 'k', pretend the mode is SImode.
   If CODE is 'q', pretend the mode is DImode.
   If CODE is 'x', pretend the mode is V4SFmode.
   If CODE is 't', pretend the mode is V8SFmode.
   If CODE is 'h', pretend the reg is the 'high' byte register.
   If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
   If CODE is 'd', duplicate the operand for AVX instruction.
 */

아래에 대한 의견 ix86_print_operand() 예를 들어보세요:

b - 표시된 피연산자에 대한 레지스터의 QImode 이름을 인쇄합니다.

피연산자[0]가 reg 0이면 %b0은 %al을 인쇄합니다.

몇 가지 유용한 옵션이 아래에 나열되어 있습니다. 출력 템플릿 ~의 GCC 내부 선적 서류 비치:

'%cdigit'은 정상적으로 즉각적인 오페라를 나타내는 구문없이 일정한 값인 피연산자를 대체하는 데 사용될 수 있습니다.

'%ndigit'은 인쇄하기 전에 상수의 값이 부정된다는 것을 제외하고 '%cdigit'과 같습니다.

'%adigit'는 실제 피연산자가 주소로 처리 된 마치 메모리 참조 인 것처럼 피연산자를 대체하는 데 사용될 수 있습니다."로드 주소"명령어를 출력 할 때 유용 할 수 있습니다. 종종 그러한 명령에 대한 어셈블러 구문은 마치 메모리 참조 인 것처럼 피연산자를 작성해야하기 때문입니다.

'%ldigit'는 label_ref를 점프 명령으로 대체하는 데 사용됩니다.

'%='는 전체 컴파일의 각 명령어에 고유 한 숫자를 출력합니다.이것은 여러 어셈블러 명령을 생성하는 단일 템플릿에서 로컬 레이블을 두 번 이상 참조하는 데 유용합니다.

'%c2' 구성을 사용하면 오프셋을 사용하여 LEA 명령어의 형식을 적절하게 지정할 수 있습니다.

#define ASM_LEA_ADD_BYTES(ptr, bytes)                            \
    __asm volatile("lea %c1(%0), %0" :                           \
                   /* reads/writes %0 */  "+r" (ptr) :           \
                   /* reads */ "i" (bytes));

'에서 중요하지만 드물게 문서화된 'c'에 주목하세요.%c1'.이 매크로는 다음과 같습니다.

ptr = (char *)ptr + bytes

그러나 일반적인 정수 산술 실행 포트를 사용하지 않습니다.

추가하려면 편집하세요:

x64에서 직접 호출하는 것은 문서화되지 않은 또 다른 수정자가 필요하기 때문에 어려울 수 있습니다.'%P0' (PIC용인 것 같습니다)

#define ASM_CALL_FUNC(func)                                         \
    __asm volatile("call %P0") :                                    \
              /* no writes */ :                                     \
              /* reads %0 */ "i" (func))                           

소문자 'p' 수정자도 GCC에서 동일하게 작동하는 것으로 보이지만 ICC에서는 대문자 'P'만 인식됩니다.자세한 내용은 아마도 다음에서 확인할 수 있습니다. /gcc/config/i386/i386.c."'p'"를 검색하세요.

고민하고 있는 사이...Chris의 두 번째 솔루션에서는 "q" 제약 조건을 대문자 "Q" 제약 조건으로 바꿔야 합니다.

int
test(int x)
{
    int y;
    asm ("xchg %b0, %h0" : "=Q" (y) : "0" (x));
    return y;
}

"q"와 "Q"는 64비트 모드에서 약간 다릅니다. 여기서 모든 정수 레지스터(ax, bx, cx, dx, si, di, sp, bp, r8-r15)에 대해 가장 낮은 바이트를 얻을 수 있습니다. .하지만 두 번째로 낮은 바이트만 얻을 수 있습니다(예:ah) 4개의 원래 386 레지스터(ax, bx, cx, dx)에 대한 것입니다.

분명히 이것을 수행하는 트릭이 있습니다 ...하지만 그다지 효율적이지 않을 수도 있습니다.32비트 x86 프로세서는 일반적으로 느린 범용 레지스터에서 16비트 데이터를 조작할 때.성능이 중요하다면 벤치마킹해야 합니다.

이것이 (a) 성능이 중요하고 (b) 훨씬 더 빠르다는 것이 입증되지 않는 한 유지 관리의 번거로움을 덜고 C에서 수행할 것입니다.

uint32_t y, hi=(x&~0xffff), lo=(x&0xffff);
y = hi + (((lo >> 8) + (lo << 8))&0xffff);

GCC 4.2 및 -O2를 사용하면 6개의 명령어로 최적화됩니다.

알았어.글쎄요, 계속해서 재사용하게 될 원시적인 루틴이라면, 저는 그것에 대해 논쟁의 여지가 없습니다...Chris가 지적한 레지스터 이름 지정 요령은 제가 기억해야 할 좋은 것입니다.

표준 GCC 문서에도 포함되면 좋을 것 같습니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top