2013-11-20 15 views
6

Tôi có một chức năng với chữ ký:Lấy đối số của một thủ tục lắp ráp x64 MASM

extern "C" int foo(int a, int b, int c, int d, int e); 

mà là trong thực tế viết bằng lắp ráp.

Với ml (32 bit), sử dụng quy ước gọi tiêu chuẩn mà bạn có thể khá nhiều viết

.code 
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD 

    mov eax, d 
    mov ebx, e 

và bắt đầu sử dụng những nhãn để truy cập vào lập luận của bạn

Với ml64 (64 bit) thì fastcall là chỉ có quy ước. Tôi không có rắc rối truy cập vào các đối số đầu tiên được lưu giữ trong sổ đăng ký, nhưng các vấn đề tiếp cận những người trong ngăn xếp (e trong ví dụ này): Tôi cố gắng

.code 
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD 

.code 
foo PROC e: DWORD 

nhưng giá trị trong e là rác.

Tôi thấy rằng nếu tôi sử dụng địa chỉ ngăn xếp trực tiếp, tôi tìm thấy giá trị.

.code 
foo PROC e: DWORD 

    mov eax, r9     ; d 
    mov ebx, DWORD PTR[rbp + 48] ; e 

Có một cách khác?

Trả lời

3

Tài liệu giải thích tất cả mọi thứ ... Trong Windows, bốn thông số nguyên đầu tiên được thông qua trong thanh ghi RCX, RDX, R8, R9 và dấu chấm động trong XMM0, XMM1, XMM2, XMM3, bất cứ điều gì hơn bốn thông số được truyền vào ngăn xếp phía trên không gian bóng. Đối với hệ điều hành kiểu Unix, nó có một chút khác biệt.

Vì vậy, ví dụ bạn là chính xác - mov ebx, DWORD PTR[rbp + 48] ; e

bóng không gian = 32 + lưu RBP = 40 + số 5 = 48

0

cho

extern "C" int foo(int a, int b, int c, int d, int e); 

tôi phát hiện ra rằng visual studio 2010 doesn 't lưu con trỏ cơ sở RBP nếu

.code 
foo PROC 

nhưng lưu con trỏ cơ sở nếu

.code 
foo PROC e: DWORD 

Phiên bản sau (vs2015) không cho phép mã thứ hai.

There is an optional optimization in x64 systems where RBP is not used (phát hiện ra một cách khó khăn). Nó nói:

Việc sử dụng thông thường của% RBP như một con trỏ khung cho khung ngăn xếp có thể tránh được bằng cách sử dụng% RSP (stack pointer) để chỉ mục vào khung stack.Kỹ thuật này tiết kiệm hai hướng dẫn trong phần mở đầu và phần kết và tạo thêm một thanh ghi đa năng bổ sung (% rbp) có sẵn.

Vì vậy, có thể là foo PROC e: DWORD không biên dịch (vs2015) hoặc foo PROC bị lỗi vì RBP là rỗng.

Các cách chính xác để lấy lý lẽ chồng là sử dụng con trỏ ngăn xếp RSP cho rằng

đâu num_saved_reg là số đăng ký theo quy định tại chỉ thị PROC. Vì vậy, khi rbp không được lưu (nếu không thì hãy thêm 8)

PROC -> DWORD PTR[rsp + 40] 
PROC use RDI -> DWORD PTR[rsp + 40 + 8] 
PROC use RDI RSI RBX -> DWORD PTR[rsp + 40 + 24] 
Các vấn đề liên quan