Trong CDECL, các đối số được đẩy lên ngăn xếp theo thứ tự đảo ngược, trình gọi xóa ngăn xếp và kết quả được trả về thông qua sổ đăng ký bộ xử lý (sau này tôi sẽ gọi nó là "thanh ghi A"). Trong STDCALL có một sự khác biệt, người gọi không xóa ngăn xếp, người gọi thì làm.
Bạn đang hỏi cái nào nhanh hơn. Không một ai. Bạn nên sử dụng quy ước gọi bản địa miễn là bạn có thể. Chỉ thay đổi quy ước nếu không có lối thoát, khi sử dụng các thư viện bên ngoài yêu cầu sử dụng quy ước nhất định.
Bên cạnh đó, có những quy ước khác mà trình biên dịch có thể chọn làm mặc định, tức là trình biên dịch Visual C ++ sử dụng FASTCALL về mặt lý thuyết nhanh hơn vì sử dụng nhiều thanh ghi bộ xử lý hơn.
Thông thường, bạn phải cung cấp một chữ ký quy ước gọi thích hợp để gọi lại các hàm được truyền đến một số thư viện bên ngoài, tức là gọi lại qsort
từ thư viện C phải là CDECL (nếu trình biên dịch theo mặc định sử dụng quy ước khác thì chúng ta phải đánh dấu gọi lại là CDECL) hoặc các lệnh gọi lại WinAPI khác nhau phải là STDCALL (toàn bộ WinAPI là STDCALL).
Trường hợp thông thường khác có thể là khi bạn đang lưu trữ con trỏ đến một số hàm bên ngoài, tức là để tạo một con trỏ tới hàm WinAPI, định nghĩa kiểu của nó phải được đánh dấu bằng STDCALL.
Và dưới đây là một ví dụ cho thấy cách trình biên dịch làm điều đó:
/* 1. calling function in C++ */
i = Function(x, y, z);
/* 2. function body in C++ */
int Function(int a, int b, int c) { return a + b + c; }
CDECL:
/* 1. calling CDECL 'Function' in pseudo-assembler (similar to what the compiler outputs) */
push on the stack a copy of 'z', then a copy of 'y', then a copy of 'x'
call (jump to function body, after function is finished it will jump back here, the address where to jump back is in registers)
move contents of register A to 'i' variable
pop all from the stack that we have pushed (copy of x, y and z)
/* 2. CDECL 'Function' body in pseudo-assembler */
/* Now copies of 'a', 'b' and 'c' variables are pushed onto the stack */
copy 'a' (from stack) to register A
copy 'b' (from stack) to register B
add A and B, store result in A
copy 'c' (from stack) to register B
add A and B, store result in A
jump back to caller code (a, b and c still on the stack, the result is in register A)
CÀI ĐẶT:
/* 1. calling STDCALL in pseudo-assembler (similar to what the compiler outputs) */
push on the stack a copy of 'z', then a copy of 'y', then a copy of 'x'
call
move contents of register A to 'i' variable
/* 2. STDCALL 'Function' body in pseaudo-assembler */
pop 'a' from stack to register A
pop 'b' from stack to register B
add A and B, store result in A
pop 'c' from stack to register B
add A and B, store result in A
jump back to caller code (a, b and c are no more on the stack, result in register A)