2009-08-09 33 views
8

Tôi vừa mới bắt đầu làm việc với ASM và tôi không chắc liệu sự hiểu biết của tôi về các cuộc gọi thủ tục có đúng không.làm thế nào để các cuộc gọi thủ tục làm việc trong assembler?

nói tại một số điểm trong các mã có một cuộc gọi thủ tục

call dword ptr[123] 

và thủ tục bao gồm chỉ có một lệnh, ret:

ret 0004 

những gì sẽ là ảnh hưởng của cuộc gọi thủ tục này và giá trị trả về sẽ được lưu ở đâu? Tôi đọc ở đâu đó rằng giá trị trả về 2 byte sẽ được lưu trữ trong AX, nhưng khi tôi thay thế cuộc gọi thủ tục theo

mov AX, 0004 

(cùng với NOP cần thiết) chương trình bị treo.

Trả lời

12

trong lắp ráp x86 tham số để hướng dẫn ret có nghĩa là:

RET immediate

Return to gọi thủ tục và bật ngay byte từ ngăn xếp.

(trích dẫn từ Intel® 64 and IA-32 Architectures Software Developer's ManualsVol 2B)

Vì vậy, khi bạn gõ:

ret 0004 

Bạn đang nói CPU để trở về giảng dạy ngay sau khi call, và để bật 4 byte tắt ngăn xếp. Điều này thật tuyệt nếu bạn đẩy 4 byte vào ngăn xếp trước cuộc gọi.

push eax 
call dword ptr[123] 

Lưu ý rằng việc này không liên quan đến giá trị trả về. Trong thực tế, một thủ tục trong Assembly không có cách nào xác định rằng một giá trị là một giá trị trả về. Điều này là tất cả được thực hiện theo quy ước. Hầu hết các trình biên dịch mà tôi biết sẽ sử dụng EAX để giữ giá trị trả lại, nhưng điều này là đúng chỉ vì hàm gọi sẽ mong đợi kết quả ở đó.

Vì vậy, mã gọi của bạn sẽ là:

call dword ptr [123] 
mov dword ptr [result], eax 

và chức năng của bạn mà trả về giá trị 4 sẽ là:

mov eax, 4 
ret 
+0

cảm ơn! hầu hết các hướng dẫn tôi googled chỉ được sử dụng ret, và không giải thích ret ngay lập tức hoạt động. Tôi đã bối rối hơn khi bộ ghép LLVM dường như có một lệnh "ret ". – int3

+0

có lý do nào khiến RET có thể quay trở lại một nơi nào đó không phải là cuộc gọi không? Tôi vừa tạo ra một câu hỏi và tìm thấy câu hỏi này trong các câu hỏi liên quan – lisovaccaro

+0

có, nếu bạn thao tác địa chỉ trả về 'CALL' được đẩy lên ngăn xếp. –

-1

Tôi không nghĩ rằng giá trị trả về được lưu trữ trong thanh ghi AX

+0

mọi ý tưởng ở đâu, sau đó? – int3

+0

@ int3: Nó phụ thuộc vào quy ước gọi điện. Không có gì tự động ở đây. Hàm gọi và hàm được gọi phải đồng ý về nơi giá trị trả về là. –

1
// possibly there are arguments pushed here 
... 
call dword ptr[123] // push next OP code offset in the stack and jump to procedure 

// procedure 
... 
ret 0004 // pop offset, set EIP to that offset and decrease ESP by 4 

chúng tôi thêm giảm ESP nếu chúng ta đã đẩy đối số trong ngăn xếp trước khi gọi thủ tục.


Nếu có đối số được đẩy, chương trình của bạn bị lỗi vì bạn không bật chúng. Giá trị trả về cho quy trình hiện tại sẽ sai vì nó sẽ nhận được một giá trị từ một trong các đối số được đẩy làm bù trừ.

2

Tất cả đều phụ thuộc vào calling convention đang được sử dụng. Tôi sẽ không lặp lại bài viết trên Wikipedia ở đây, chỉ cần đọc định nghĩa.

Trong ví dụ C calling convention, giá trị trả lại sẽ bằng EAX/AX/AL. Hướng dẫn đơn của bạn không có một: Nó là một hàm void lấy khoảng 4 byte tham số (có thể là một int) không làm gì cả. Vì nó là nhiệm vụ của callee để làm sạch ngăn xếp trong quy ước gọi điện thoại này, bỏ qua để làm điều đó và thay thế cuộc gọi bằng một 'trục rìu' không hoạt động.

Ngoài ra tôi nghi ngờ bạn có thể đang sửa đổi với việc lắp ráp 32 bit trong khi đọc tài liệu 16 bit. Nó không phải là một vấn đề lớn, nhưng bạn nên nhận thức được sự khác biệt.

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