2013-03-04 37 views
8

Trong gcc, bạn có thể khai báo rằng một biến cục bộ phải được đặt trong thanh ghi bằng cú pháp sau.Cách chuyển các thông số chức năng vào sổ đăng ký với từ khóa gcc asm

register int arg asm("eax"); 

Trong một số mã cũ Tôi tìm thấy trên internet cú pháp này đã được sử dụng để khai báo rằng các tham số để một chức năng nên được thông qua trong một thanh ghi:

void foo(register int arg asm("eax")) 

Nhưng khi tôi thử ví dụ này:

/* 
    Program to demonstrate usage of asm keyword to allocate register for a variable. 
*/ 
#include <stdio.h> 

/* Function with argument passed in register */ 
void foo(register int arg asm("eax")) 
{ 
    register int loc asm("ebx"); 
    loc = arg; 
    printf("foo() local var: %d\n", loc); 
} 

int main(void) 
{ 
    foo(42); 
    return 0; 
} 

Và biên dịch với gcc tôi nhận được một lỗi:

gcc main.c -o test-asm.exe 
main.c:7:27: error: expected ';', ',' or ')' before 'asm' 

Bây giờ câu hỏi của tôi là:
Cú pháp asm ở trên chính xác, trong gcc có nghĩa là, đối với các tham số chính thức của một hàm?
Điều này có bao giờ được hỗ trợ bởi gcc không?
Nếu đây không phải là cú pháp chính xác, làm thế nào điều này có thể được thực hiện sau đó?

Cảm ơn,
// jk

Trả lời

2

Phương pháp duy nhất tôi biết là sử dụng thuộc tính fastcall:

(GCC Manual phần 6,30) http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html#Function-Attributes

fastcall

On the Intel 386, the fastcall attribute causes the compiler to pass the first argument (if of integral type) in the register ECX and the second argument (if of integral type) in the register EDX. Subsequent and other typed arguments are passed on the stack. The called function will pop the arguments off the stack. If the number of arguments is variable all arguments are pushed on the stack.

Sử dụng nó trong trên mã ví dụ sau:

__attribute__((fastcall,noinline)) int add (int a, int b) 
{ 
    return a + b; 
} 

int main() { 
    return add (1, 2); 
} 

sẽ dẫn đến:

.file "main.c" 
    .text 
.globl add 
    .type add, @function 
add: 
    pushl %ebp 
    movl %esp, %ebp 
    leal (%edx,%ecx), %eax 
    popl %ebp 
    ret 
    .size add, .-add 
.globl main 
    .type main, @function 
main: 
    pushl %ebp 
    movl %esp, %ebp 
    movl $2, %edx 
    movl $1, %ecx 
    call add 
    popl %ebp 
    ret 
    .size main, .-main 

Đừng quên đề cập đến thuộc tính fastcall trong bất kỳ tuyên bố nào trong các đơn vị dịch khác, nếu không những điều lạ có thể xảy ra.

+0

Cảm ơn đề xuất. Nhưng tôi nghĩ có thể có một cú pháp tổng quát hơn được hỗ trợ bởi gcc. –

+0

Chà, làm sao mà hơn một nửa hàm được tạo ra là phần mở đầu vô dụng/phần mở đầu của crap ... Có phải với '-O0' hay ...? –

+0

Không - với -O0 nó trở nên thú vị hơn khi các tham số được truyền qua ecx và edx vì bất kỳ lý do gì sẽ được lưu trữ trên ngăn xếp trước tiên. Đây là (không đùa) những gì gcc sẽ làm gì với -O0: 'thêm: \t pushl \t% ebp \t movl \t% esp,% ebp \t subl \t $ 8,% esp \t movl \t% ecx, -4 (% ebp) \t movl \t% edx, -8 (% ebp) \t movl \t -8 (% ebp),% eax \t movl \t -4 (% ebp),% edx \t Leal \t (% edx, % eax),% eax \t để lại \t ret' – mikyra

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