Vì một số lý do, tôi muốn trộn một chút lắp ráp với C ++ (không phải C).
Để cho phép mã có thể biên dịch được bằng Arduino IDE tiêu chuẩn, tôi không muốn sử dụng nguồn lắp ráp trực tiếp.
Tôi cũng không muốn sử dụng tệp C của trình bao bọc.
Vấn đề của tôi là như sau:
Tôi có một lớp với một thể hiện duy nhất (triển khai một số loại trình điều khiển) trông như thế này:
class cDriver {
public:
char ISR_param;
// ...
};
cDriver Driver;
Nếu tôi muốn truy cập vào ISR_param
trường hợp duy nhất này từ bên trong ISR, tôi có thể làm một cái gì đó như:
ISR (TIMER2_COMPA_Vect) {
do_something_with (Driver.ISR_param);
}
Điều này hoạt động như một bùa mê: địa chỉ của Driver.ISR_param
một hằng số, trình biên dịch chỉ cần tạo một lds r24, &Driver.ISR_param
lệnh để tải byte thích hợp làm tham số cho do_something_with
.
Bây giờ khi tôi cố gắng sao chép cùng một cơ chế với trình biên dịch mã nội tuyến, mọi thứ trở nên phức tạp hơn rất nhiều.
Địa chỉ của Driver.ISR_param
trình biên dịch C ++ chỉ được biết đến như là một nhãn mác và tôi không thể tìm cách chuyển nó đến trình biên dịch mã nội tuyến để tạo ra tương đương lds r24, <&Driver.ISR_param>
.
cố gắng làm lại biến
Việc đổi tên các biến để lắp ráp như vậy:
char global_var asm("my_var");
và một nỗ lực để sử dụng nó như vậy:
asm ("lds r24, my_var\n");
sẽ biên dịch, nhưng tạo ra lỗi liên kết ( my_var
không xác định).
Nhìn vào bảng ký hiệu đối tượng, nhãn duy nhất cho global_var
là một tên giống như C ++.
Tuy nhiên, tôi đã cố gắng đổi tên thủ thuật này, tôi không thể mang trình biên dịch để tạo my_var
nhãn.
cố gắng sử dụng các ràng buộc asm
Một ràng buộc như
asm (lds r24, %0\n" : : "I"(&global_var));
Đơn giản là sẽ không biên dịch. Tôi đã quét các loại tham số có thể và không thể tìm ra cách để trình biên dịch biết về địa chỉ đẫm máu này.
một cách giải quyết khó xử khủng khiếp
Cách duy nhất tôi tìm thấy để làm cho trình biên dịch tạo ra lệnh này đáng sợ lds r24,...
là thực hiện một cuộc gọi chức năng thực tế.
Vì vậy, bạn có thể làm một cái gì đó như:
__attribute__((always_inline)) give_me_my_friggin_variable(char data)
{
asm volatile ("cmp %0,%0\n"::"r"(data));
}
ISR (TIMER2_COMPA_Vect, ISR_NAKED) {
<some prologue to save SREG and all needed registers>
//...
give_me_my_friggin_variable(Driver.ISR_param);
// continue assembly code with r24 properly initialized
}
Điều đó sẽ tạo ra:
lds r24, <the proper address> // added by the compiler...
cmp r24,r24 // ...because of the register constraint here
Vâng, đó là loại công việc, nhưng với chi phí tạo ra một hướng dẫn hoàn toàn vô dụng.
vì vậy câu hỏi của tôi là ...
Có cách nào đơn giản hơn để cho trình biên dịch biết về địa chỉ của các biến tĩnh C ++ không?