cuốn sách gpt4 ai đã làm

gcc sử dụng lại không chính xác các thanh ghi trong asm nội tuyến

In lại Tác giả: Vũ trụ không gian Thời gian cập nhật: 2023-11-04 07:10:20 hai mươi bốn 4
mua khóa gpt4 Nike

Tôi đã triển khai macro vòng lặp trễ đơn giản cho Cortex-M4 trong chương trình C:

#define DELAY_CYCLES (F_CPU / 3000000) //F_CPU là 72000000
#define delayUS(n) __asm__ dễ bay hơi( \
"1: phụ %0, #1 \n" \
"bne 1b \n" \
: /* không có kết quả đầu ra */ \
: "r" (n * DELAY_CYCLES) /* đầu vào */ \
: "0" /* ghi đè */ \
)

điều này sẽ trì hoãn n Micro giây (giả sử các ngắt bị vô hiệu hóa). Hầu hết thời gian nó hoạt động tốt. Tuy nhiên, tôi thấy rằng nó không hoạt động bình thường trong một chức năng sử dụng nó hai lần:

kiểm tra khoảng trống tĩnh (uint8_t num) {
digitalWrite(12, 1);
độ trễUS(10);
digitalWrite(13, 1);
độ trễUS(10);
digitalWrite(12, 0);
digitalWrite(13, 0);
}

(Đây là một ứng dụng thực tế số nhưng đã bị loại bỏ thành chức năng này khi gỡ lỗi vấn đề này. Nó cũng được nội tuyến vào chủ yếu , do đó nhãn được tháo rời. )

Những gì đang xảy ra ở đây là đúng độ trễUS() Cuộc gọi thứ hai không bao giờ hoàn thành. Việc kiểm tra tổ hợp được tạo đã phát hiện ra vấn đề:

 528: 2701 lượt r7, #1
52a: 6037 str r7, [r6, #0] ;digitalWrite(12, 1)
52c: 23f0 mov r3, #240 ;delayUS(10); 10 * DELAY_CYCLES = 240
52e: 3b01 sub r3, #1
530: d1fd bne.n 52e

532: 4c0d ldr r4, [pc, #52]
534: 6027 str r7, [r4, #0] ;digitalWrite(13, 1)

536: 3b01 subs r3, #1 ;delayUS(10), nhưng r3 vẫn bằng 0
538: d1fd bne.n 536

53a: 2300 lượt r3, #0
53c: 6033 str r3, [r6, #0] ;digitalWrite(12, 0)

Vì lý do nào đó, gcc không khởi tạo lại trước khi sử dụng nó trong vòng lặp trễ thứ hai r3, do đó, nó không bị trễ 240 lần lặp (10µs), mà là 2^32 (khoảng 3 phút).

Với biến thể này, vấn đề sẽ biến mất:

__attribute__((used)) int giả;
#define delayUS(n) __asm__ dễ bay hơi( \
"1: phụ %0, #1 \n" \
"bne 1b \n" \
: "=r" (giả) /* không có kết quả đầu ra */ \
: "0" (n * DELAY_CYCLES) /* đầu vào */ \
: "0" /* ghi đè */ \
)

Tạo mã chính xác hơn:

 528: 2701 lượt r7, #1
52a: 23f0 mov r3, #240 ;r3 = 10 * DELAY_CYCLES
52c: 6037 str r7, [r6, #0] ;digitalWrite(12, 1)
52e: 461a mov r2, r3 ;r2 = r3

530: 3a01 sub r2, #1 ;delayUS(r2)
532: d1fd bne.n 530

534: 4c0d ldr r4, [pc, #52]
536: 6027 str r7, [r4, #0] ;digitalWrite(13, 1)

538: 3b01 sub r3, #1 ;delayUS(r3)
53a: d1fd bne.n 538

53c: 4a0c ldr r2, [pc, #48]
53e: 6013 str r3, [r2, #0] ;digitalWrite(12, 0)

Ở đây, nó nhận ra chính xác rằng vòng lặp trễ làm hỏng thanh ghi đầu vào của nó và do đó không sử dụng lại nó mà không khởi tạo nó r3(Nó sử dụng r2 như một trong số chúng chứ không phải là một vòng lặp. )

Vậy tại sao gcc không nhận ra rằng phiên bản trước cũng bị hỏng đầu vào khi nó được liệt kê trong danh sách bị hỏng?

câu trả lời hay nhất

Vấn đề là danh sách "clobbers" là danh sách tên đăng ký hoặc các chuỗi đặc biệt "cc" và "bộ nhớ". Vì không có thanh ghi nào có tên "0" nên việc đưa nó vào danh sách ghi đè là vô nghĩa. Thật không may, gcc không đưa ra cảnh báo cho bạn. Thay vào đó, như tài liệu gcc chỉ ra:

Cảnh báo: Không sửa đổi nội dung của các toán hạng chỉ có đầu vào (ngoại trừ các đầu vào được gắn với đầu ra). Trình biên dịch giả định rằng khi thoát khỏi câu lệnh asm, các toán hạng này chứa các giá trị giống như trước khi thực hiện câu lệnh. sử dụng clobbers để thông báo cho trình biên dịch rằng các giá trị trong các đầu vào này đang thay đổi. Một cách giải quyết phổ biến là gắn biến đầu vào đang thay đổi với một biến đầu ra không bao giờ được sử dụng.

Cách giải quyết này là ví dụ thứ hai của bạn thực hiện và lý do nó hoạt động. Để chính xác, có lẽ bạn cũng nên thêm "cc" vào danh sách clobbers (khi bạn sửa đổi cờ) và tốt hơn hết bạn nên xóa "0" vì nó vô nghĩa.

Về c - gcc việc sử dụng lại các thanh ghi trong asm nội tuyến không chính xác, chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/28931625/

hai mươi bốn 4 0
không gian vũ trụ
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress