Kode setelah konversi tidak menjalankan tindakan tertentu [duplikat]

Dec 18 2020

Saya diberi tugas untuk mengubah kode tertentu dari C ++ ke ASM berdasarkan sintaks AT&T, jadi saya mulai dengan contoh sederhana dan mengalami masalah pertama.

kode tempat saya memulai latihan

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

yang memberikan hasil:

before: 1
after: 8

variabel terjemahan saya num adalah variabel lokal pertama jadi harus di alamat -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;
}

yang memberikan hasil:

before: 1
after: 1

mengapa kode ini tidak berpengaruh pada num var?

Jawaban

2 JHBonarius Dec 18 2020 at 02:17

Kode yang Anda tulis sangat spesifik untuk implementasi. Dalam kasus Anda, kode tersebut kemungkinan besar tidak berfungsi karena Anda menggunakan ebpregister pengalamatan 32-bit, saat Anda menjalankan mesin 64-bit, yang menggunakan rbp.

NAMUN Anda salah mendekati ini. Entah Anda menulis perakitan murni, atau Anda menggunakan perakitan inline C yang benar (diperpanjang), yang dengan benar berinteraksi dengan variabel lokal. Jika tidak, kode akan rusak segera setelah Anda mengubah sesuatu, seperti yang Anda alami sendiri.

menurut jawaban ini asm sebaris akan terlihat seperti:

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

sehingga kode Anda akan terlihat seperti

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

Namun, Anda tidak perlu menentukan dan menggunakan eax, sehingga kode dapat disederhanakan (dan diklarifikasi) menjadi

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