Tại sao trình biên dịch không sử dụng LSR trực tiếp


10

Xin chào Tôi đã làm việc trên một dự án bằng Arduino Uno (vì vậy ATmega328p) trong đó thời gian là khá quan trọng và vì vậy tôi muốn xem hướng dẫn nào trình biên dịch đang chuyển đổi mã của tôi. Và trong đó tôi có một uint8_tcái mà tôi dịch chuyển một bit sang phải trên mỗi lần lặp bằng cách sử dụng data >>= 1và có vẻ như trình biên dịch đã dịch điều này thành 5 hướng dẫn ( datanằm trong r24):

mov     r18, r24
ldi     r19, 0x00
asr     r19
ror     r18
mov     r24, r18

Nhưng nếu tôi nhìn vào tài liệu hướng dẫn tập hợp, tôi thấy một hướng dẫn thực hiện chính xác điều này: lsr r24

Tôi có bỏ qua điều gì không hoặc tại sao trình biên dịch cũng không sử dụng? Các thanh ghi r18r19không được sử dụng ở bất cứ nơi nào khác.

Tôi đang sử dụng Ardunio nhưng nếu tôi đúng thì nó chỉ sử dụng avr-gcctrình biên dịch bình thường . Đây là mã (được cắt xén) tạo ra chuỗi:

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

Theo như tôi có thể thấy Ardunino IDE đang sử dụng trình biên dịch gcc AVR được cung cấp bởi hệ thống là phiên bản 6.2.0-1.fc24. Cả hai đều được cài đặt thông qua trình quản lý gói nên được cập nhật.


1
Việc lắp ráp dường như không tương ứng với mã C.
Eugene Sh.

Chà, tôi đã biên dịch nó bằng Ardunio IDE và sau đó được sử dụng avr-objdumptrên tập tin elf. Cái gì dường như không tương ứng?
xZise

1
@Eugene Sh .: Đây không tương ứng với mã C. Nó chỉ tương ứng với dòngdata >>= 1;
Curd

1
Đây là một trong những trường hợp "sử dụng ca thay vì chia" là lời khuyên sai. Nếu bạn làm / = 2 thay vào đó trình biên dịch sẽ tạo lsr r24; (mẹo: hãy thử trình thám hiểm gcc để chơi xung quanh với việc tạo mã asm)
PlasmaHH

Có gì trình biên dịch? Bộ xử lý gì? Nó thực sự nên rõ ràng đây là thông tin cần thiết cho câu hỏi có ý nghĩa.
Olin Lathrop

Câu trả lời:


18

Theo đặc tả ngôn ngữ C, bất kỳ giá trị nào có kích thước nhỏ hơn kích thước int(phụ thuộc vào trình biên dịch cụ thể; trong trường hợp của bạn intrộng 16 bit) liên quan đến bất kỳ thao tác nào (trong trường hợp của bạn >>) được đưa lên inttrước một thao tác.
Hành vi này của trình biên dịch được gọi là khuyến mãi số nguyên .

Và đó chính xác là những gì trình biên dịch đã làm:

  • r19 = 0 là MSByte của giá trị thăng cấp nguyên của data.
  • (r19, r18) đại diện cho tổng giá trị được thăng cấp của số datađó sau đó được dịch chuyển sang phải một bit bởi asr r19ror 18.
  • Kết quả sau đó được ngầm định quay trở lại uint8_tbiến của bạn data:
    mov r24, r18, tức là MSByte trong r19 bị vứt đi.

Chỉnh sửa:
Tất nhiên trình biên dịch có thể tối ưu hóa mã.
Cố gắng tái tạo vấn đề tôi thấy rằng ít nhất là với phiên bản avr-gcc 4.9.2, sự cố không xảy ra. Nó tạo mã rất hiệu quả, tức là dòng C data >>= 1;được biên dịch thành một lsr r24lệnh duy nhất . Vì vậy, có thể bạn đang sử dụng một phiên bản trình biên dịch rất cũ.


2
Đó không phải là một sự lãng phí hoàn toàn bởi vì đôi khi bạn cần mã không được tối ưu hóa để gỡ lỗi ở cấp độ trình biên dịch. Sau đó, bạn rất vui mừng nếu bạn có mã không được tối ưu hóa.
Sữa đông

3
Nếu tôi nhớ chính xác -mint8 là cờ để tạo số nguyên 8 bit. Tuy nhiên điều này có rất nhiều tác dụng phụ không mong muốn. Xin lỗi, tôi không thể nhớ chúng là gì bây giờ, nhưng tôi không bao giờ sử dụng cờ vì chúng. Tôi đã dành rất nhiều thời gian để so sánh avr-gcc với một trình biên dịch thương mại nhiều năm trước.
Jon

1
Ồ đúng vậy, tiêu chuẩn C yêu cầu số nguyên ít nhất là 16 bit, do đó, việc sử dụng -mint8 sẽ phá vỡ tất cả các thư viện.
Jon

9
Nigel Jones đã nói trong "Mã C hiệu quả cho Vi điều khiển 8 bit" đại loại như: "... Các quy tắc quảng bá số nguyên của C có lẽ là tội ác ghê tởm nhất đối với những người lao động trong thế giới 8 bit" ...
Dirceu Coleues Jr

1
@Jonas Wielicki: giải pháp tốt nhất cho vấn đề là sử dụng trình biên dịch tốt hơn. Ví dụ: với phiên bản avr-gcc 4.9.2 Tôi không thể tái tạo vấn đề: Đối với dòng mã C d >>= 1;tôi chỉ nhận được một lsr r24hướng dẫn duy nhất . Có thể xZise đang sử dụng một phiên bản trình biên dịch rất cũ.
Sữa đông
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.