2011-01-09 26 views
5

Có cách nào để buộc gcc chuyển các tham số của hàm trên ngăn xếp không?Buộc gcc chuyển các tham số trên ngăn xếp

Tôi không muốn sử dụng thanh ghi để chuyển thông số.

Cập nhật: I'am sử dụng cánh tay-gcc từ CodeSourcery

+3

Tại sao truyền tham số trong sổ đăng ký một điều xấu? –

+0

Nó không phải là một điều xấu. Tôi chỉ muốn các tham số được truyền theo cách này bởi vì I'am // mô phỏng // một quá trình tạo luồng (và phân bổ stack). – cojocar

+0

Kiến trúc/ABI nào? – ephemient

Trả lời

0

Theo: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf

Bốn thanh ghi đầu tiên r0-r3 (a1-a4) được sử dụng để vượt qua những giá trị lý luận thành một chương trình con và trả lại kết quả giá trị từ một hàm. Họ cũng có thể được sử dụng để giữ các giá trị trung gian trong một thường lệ (nhưng, nói chung, chỉ giữa các cuộc gọi chương trình con).

Có, trên ARM, không có quy ước gọi điện nào khác nhưng mặc định, tôi biết. Và đây là lý do:

  1. Tại sao bạn muốn? Chức năng của bạn sẽ không thể gọi được dưới dạng được biên dịch bởi các chức năng khác, tạo ra một mớ hỗn độn tương thích.
  2. Cuộc gọi của bạn đến các chức năng hệ thống tuân thủ ABI sẽ không hoạt động, trừ khi trình biên dịch có thể phân biệt giữa các quy ước gọi điện. Bây giờ, tôi biết trong quá khứ có những quy ước gọi khác nhau cho x86-32, nhưng lưu ý cách x64 đơn giản hơn (AMD64 so với bất kỳ điều gì Microsoft đã làm). Tại sao, khi thiết kế ARM calling convention, bạn có cho phép nhiều quy ước gọi điện khác nhau không? Nó tạo ra một mớ hỗn độn tương thích.
+1

Có bạn đã đúng. Đó là một điều kỳ quặc với điều này, đặc biệt là vì những lý do bạn đã đề cập. Ý tưởng là hàm được định nghĩa là phần chính của một luồng - trong môi trường tùy chỉnh (OS). Hệ điều hành tùy chỉnh sẽ đẩy đối số của chuỗi trên ngăn xếp. Để tôn trọng ABI, có hai cách giải quyết: đặt đối số vào r0 hoặc khai báo * thread_func (uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3, void * param) *. Cảm ơn! – cojocar

+1

Tại sao không đặt chúng vào sổ đăng ký? Bạn cần phải giữ lại các thanh ghi trên các luồng, nhưng bạn phải anyway - hãy tưởng tượng nếu bạn chuyển đổi các luồng trong khi thực thi và các giá trị đăng ký của hàm cũ vẫn còn ở vị trí ... nếu OSes thực hiện điều này, nó sẽ rất lộn xộn. –

+0

Chủ đề được tạo từ không gian người dùng và không có API (syscall) để đặt giá trị đăng ký cho chuỗi mới tạo. – cojocar

1

Bạn có thể thử gói các tham số trong cấu trúc; ví dụ, nếu chức năng của bạn là int calc_my_sum(int x, int y) {return x+y;} bạn có thể thay đổi nó như sau (xấu xí):

struct my_x_y { 
    int x, y; 
    my_x_y(): x(0), y(0) {} // a non-trivial constructor to make the type non-POD 
}; 

int calc_my_sum(my_x_y x_and_y) { 
    // passing non-POD object by value forces to use the stack 
    return x_and_y.x + x_and_y.y; 
} 

Ngoài ra, bạn có thể chỉ cần thêm 4 thông số giả để sử dụng hết đăng ký, vì vậy các thông số khác sẽ sử dụng ngăn xếp:

struct force_stack_usage { 
    int dummy0, dummy1, dummy2, dummy3; 
} 

int calc_my_sum(force_stack_usage, int x, int y) { 
    return x + y; 
} 
+0

Đẹp hack! Giải pháp đầu tiên là C++ chỉ, tôi quên đề cập đến rằng tôi cần một giải pháp C. Cảm ơn. – cojocar

+1

Không cần một hàm tạo C++ kỳ lạ để đạt được những gì bạn muốn. Trong các cấu trúc C được sao chép đơn giản trên ngăn xếp. Trong C99, bạn thậm chí có thể gọi hàm với 'calc_my_sum ((my_x_y) {.x = 5, .y = 7})' hoặc bọc một thứ như vậy trong macro mà không gặp vấn đề gì. –

0

Nơi lưu trữ biến cục bộ phụ thuộc vào cách bạn sẽ sử dụng biến đó. Nếu bạn cần để có được một địa chỉ của biến địa phương, biến địa phương chỉ có thể được lưu trữ trên ngăn xếp. Vì vậy, khi bạn vượt qua chương trình con của bạn một con trỏ, tham số này sẽ được chuyển qua ngăn xếp.

+0

Tôi không chắc liệu đây có phải là câu hỏi hay không ... – Nanomurf

Các vấn đề liên quan