Hai Saya sudah mengerjakan proyek menggunakan Arduino Uno (jadi ATmega328p) di mana waktunya cukup penting dan jadi saya ingin melihat ke dalam instruksi mana kompiler mengubah kode saya. Dan di sana saya memiliki uint8_t
yang saya menggeser satu bit ke kanan pada setiap iterasi menggunakan data >>= 1
dan tampaknya kompiler menerjemahkan ini ke dalam 5 instruksi ( data
ada di r24
):
mov r18, r24
ldi r19, 0x00
asr r19
ror r18
mov r24, r18
Tetapi jika saya melihat dokumentasi set instruksi saya melihat instruksi yang melakukan hal ini: lsr r24
Apakah saya mengabaikan sesuatu atau mengapa kompiler tidak menggunakan ini juga? Register r18
dan r19
tidak digunakan di tempat lain.
Saya menggunakan Ardunio tetapi jika saya benar itu hanya menggunakan avr-gcc
kompiler normal . Ini adalah kode (dipangkas) yang menghasilkan urutan:
ISR(PCINT0_vect) {
uint8_t data = 0;
for (uint8_t i = 8; i > 0; --i) {
// asm volatile ("lsr %0": "+w" (data));
data >>= 1;
if (PINB & (1 << PB0))
data |= 0x80;
}
host_data = data;
}
Sejauh yang saya bisa lihat, Ardunino IDE menggunakan kompiler gcc AVR yang disediakan oleh sistem yang merupakan versi 6.2.0-1.fc24. Keduanya dipasang melalui palungan paket sehingga harus diperbarui.
avr-objdump
pada file elf ... Apa yang tampaknya tidak sesuai?data >>= 1;
Jawaban:
Menurut spesifikasi bahasa C, nilai apa pun yang ukurannya kurang dari ukuran
int
(tergantung pada kompiler tertentu; dalam kasus Andaint
lebar 16-bit) yang terlibat dalam operasi apa pun (dalam kasus Anda>>
) dikirim keint
sebelum operasi.Perilaku kompiler ini disebut promosi integer .
Dan itulah yang dilakukan oleh kompiler:
data
.data
yang kemudian bergeser ke kanan sedikit demi sedikit olehasr r19
danror 18
.uint8_t
variabeldata
:mov r24, r18
, yaitu MSByte di R19 dibuang.Sunting:
Tentu saja penyusun dapat mengoptimalkan kode.
Mencoba mereproduksi masalah saya menemukan bahwa setidaknya dengan avr-gcc versi 4.9.2 masalah tidak terjadi. Ini menciptakan kode yang sangat efisien, yaitu C-line
data >>= 1;
dikompilasi menjadi hanya satulsr r24
instruksi tunggal . Jadi mungkin Anda menggunakan versi kompiler yang sangat lama.sumber
d >>= 1;
saya hanya mendapatkan satulsr r24
instruksi tunggal . Mungkin xZise menggunakan versi kompiler yang sangat lama.