변환 후 코드가 지정된 작업을 실행하지 않음 [중복]

Dec 18 2020

AT & T 구문을 기반으로 특정 코드를 C ++에서 ASM으로 변환하는 작업이 주어 졌기 때문에 간단한 예제로 시작하여 첫 번째 문제가 발생했습니다.

연습을 시작한 코드

void func() {
  int num = 1;
  std::cout << "before: " << num << std::endl;
  num = num << 3;
  std::cout << "after: " << num << std::endl;
}

결과를 제공합니다.

before: 1
after: 8

내 번역 변수 num은 첫 번째 지역 변수이므로 주소 -4 (% ebp)에 있어야합니다.

void func() {
  int num = 1;
  std::cout << "before: " << num << std::endl;
  asm (
    "mov -4(%ebp), %eax         \n"
    "sall $3, %eax              \n"
    "mov %eax, -4(%ebp)         \n"
  );
  std::cout << "after: " << num << std::endl;
}

결과를 제공합니다.

before: 1
after: 1

이 코드가 num var에 영향을 미치지 않는 이유는 무엇입니까?

답변

2 JHBonarius Dec 18 2020 at 02:17

작성중인 코드는 구현에 따라 매우 다릅니다. 귀하의 경우에는 ebp32 비트 주소 지정 레지스터를 사용하고 .NET을 사용하는 64 비트 컴퓨터에서 실행 중이기 때문에 코드가 작동하지 않을 수 있습니다 rbp.

그러나 당신은 이것에 잘못 접근하고 있습니다. 순수 어셈블리를 작성하거나 로컬 변수와 올바르게 인터페이스하는 올바른 (확장) C 인라인 어셈블리를 사용합니다. 그렇지 않으면 경험 한 것처럼 무언가를 변경하자마자 코드가 깨질 것입니다.

이 답변에 따르면 인라인 asm은 다음과 같아야합니다.

asm ( "assembly code"
    : output operands                  /* optional */
    : input operands                   /* optional */
    : list of clobbered registers      /* optional */
);

그래서 당신의 코드는

asm (
    "mov %0, %%eax;"
    "sal $3, %%eax;"
    "mov %%eax, %1;"
    :"=r" (num)
    :"r" (num)
    :"%eax"
);

그러나을 지정하고 사용할 필요가 없으므로 eax코드를 다음과 같이 단순화 (및 명확화) 할 수 있습니다.

asm (
    "sal $3, %[num];"
    :[num] "+r" (num)
);