Dönüşümden sonraki kod, belirli bir eylemi yürütmez [yineleme]

Dec 18 2020

AT&T sözdizimine dayalı olarak belirli bir kodu C ++ 'dan ASM'ye dönüştürmek için bir görev verildi, bu yüzden basit örneklerle başladım ve ilk sorunla karşılaştım.

egzersize başladığım kod

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

sonuç verir:

before: 1
after: 8

çeviri değişkenim num ilk yerel değişkendir, bu nedenle -4 (% ebp) adresinde olmalıdır

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;
}

sonuç verir:

before: 1
after: 1

neden bu kodun num var üzerinde etkisi yoktur?

Yanıtlar

2 JHBonarius Dec 18 2020 at 02:17

Yazdığınız kod uygulamaya özeldir. Sizin durumunuzda, kod büyük olasılıkla çalışmaz çünkü ebp32 bitlik bir adresleme yazmacı kullanıyorsunuz, 64 bitlik bir makinede çalışırken, kullanan rbp.

ANCAK buna yanlış yaklaşıyorsunuz. Ya saf derleme yazarsınız ya da yerel değişkenlerle doğru şekilde arabirim oluşturan doğru (genişletilmiş) C satır içi derlemesini kullanırsınız. Aksi takdirde, kendinizi deneyimlediğiniz gibi, bir şeyi değiştirir değiştirmez kod kırılacaktır.

bu yanıta göre satır içi asm şöyle görünmelidir:

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

böylece kodunuz şöyle görünebilir

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

Ancak, belirtmeniz ve kullanmanız gerekmez eax, bu nedenle kod basitleştirilebilir (ve açıklığa kavuşturulabilir)

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