Truy cập biến tĩnh C ++ từ gcc inline asm


7

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_paramtrườ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_parammột hằng số, trình biên dịch chỉ cần tạo một lds r24, &Driver.ISR_paramlệ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_paramtrì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_varkhông xác định).

Nhìn vào bảng ký hiệu đối tượng, nhãn duy nhất cho global_varlà 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_varnhã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?

Câu trả lời:


5

Thử cái này:

asm volatile("lds r24, %0" : : "i" (&Driver.ISR_param));

Các "i"hạn chế có nghĩa là bạn cung cấp một hằng số nguyên. Nó có thể là bất kỳ số nguyên nào, không giống như "I"ràng buộc chữ hoa được giới hạn ở các số nguyên dương 6 bit.

Phụ lục : Các ràng buộc được hỗ trợ bởi gcc được liệt kê trong tài liệu gcc, phần Ràng buộc cho asmtoán hạng :

  • Các "i"ràng buộc được liệt kê trong tiểu mục Khâu ràng buộc đơn giản và được mô tả như sau:

Một toán hạng số nguyên ngay lập tức (một giá trị không đổi) được cho phép. Điều này bao gồm các hằng số tượng trưng có giá trị sẽ chỉ được biết tại thời điểm lắp ráp hoặc sau đó.

  • Các "I"ràng buộc nằm trong phần phụ của Máy Giới hạn Máy và ràng buộc với kiến ​​trúc AVR, được định nghĩa là

Hằng số lớn hơn -1, nhỏ hơn 64.


1
Dang ... Và cảm ơn :). Loại "i" này không được liệt kê trong sách hướng dẫn trực tuyến mà tôi tìm thấy. Để hoàn thiện, bạn có thể thêm một liên kết đến một tài liệu cập nhật không? Btw. Tôi tự hỏi tại sao một ví dụ về việc sử dụng trình biên dịch nội tuyến rõ ràng như vậy lại khó đến vậy.
Kuroi neko

@kuroineko: "i"Hạn chế thực sự bị thiếu trong Sách dạy nấu ăn nội tuyến của avr-libc . Tôi đã thêm một liên kết đến tài liệu gcc liệt kê nó.
Edgar Bonet

Cảm ơn rất nhiều. Tôi đoán đó là kiểu nấu ăn khá bí mật :).
Kuroi neko
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.