2013-04-23 38 views
5

Tôi nhập mã này vào c: __asm__("mov $10, %rsi"); printf("%x"), Nó in a.
Tôi gỡ lỗi trong gdb, thấy rằng kết quả lưu trữ int register esi.
CÂU HỎI: tại sao kết quả là esi?c printf ("% x"), nó in gì?

+0

Câu hỏi hay! EDIT: ybungalobill đã đánh cắp câu trả lời đó! –

+0

Làm thế nào bạn xác định được kết quả (có lẽ bạn có nghĩa là giá trị trả về của printf, mà nên là 2) được lưu trữ trong esi? – nos

+0

'__asm ​​__ (" mov $ 10,% rsi ");' chỉnh sửa giá trị 'esi/rsi', tôi đã thử một số giá trị khác. – sumous

Trả lời

11

printf("%x") cố gắng lấy đối số thứ hai, nhưng nó không có ở đó, vì vậy nó chỉ đọc bộ nhớ cần có, tìm bất kỳ thứ rác nào ở đó và in ra.

Tóm lại: đó là hành vi không xác định.

EDIT: lý do bạn thấy giá trị tương tự như trong esi đăng ký, đó là giá trị này được tính như là một phần của một số trước đó (nhưng gần đây) tính toán trong chương trình của bạn và bảo quản ở cùng một vị trí printf cố gắng đọc từ. Thực tế là hai địa điểm trùng hợp hoàn toàn ngẫu nhiên, trong phạm vi hành vi không xác định.

+1

Những gì nó tìm thấy, nó xử lý như là một int unsigned và in mã hex (trong trường hợp thấp hơn) cho rằng (đó là những gì% x không). – Thilo

+0

@ybungalobill Làm cách nào để biết địa chỉ nên ở đâu? Hay nói cách khác nó đọc từ đâu? –

+1

@Armin: Đó là "triển khai được xác định". Nhìn vào mã nguồn của thư viện/trình biên dịch của bạn, hoặc tham khảo tài liệu biên dịch hoặc tài liệu ABI của bạn. –

2

Khi gọi printf("%x"), nó xảy ra, các đối số cần thiết được đẩy vào ngăn xếp (theo thứ tự ngược lại) và cuối cùng, hàm được gọi bằng lệnh lắp ráp call. Khi cung cấp chuỗi định dạng "%x", printf() của bạn mong đợi ít nhất MỘT đối số sau, vì vậy nó sẽ đọc giá trị tiếp theo trên ngăn xếp, có thể là bất cứ điều gì ...
Hành vi này thực sự không xác định và thường là nguyên nhân để khai thác, bởi vì bạn có thể làm hỏng ngăn xếp.

Có thể một chút excourse về chủ đề này.

+0

Không phải địa chỉ trả lại được đẩy vào ngăn xếp cũng khi các đối số được đẩy theo thứ tự ngược lại? –

+0

@SheerFish: thường (bao gồm kiến ​​trúc x86 và amd64), đó là lệnh 'call' thực hiện điều đó. – ybungalobill

+0

Tôi không chắc chắn 100% bây giờ, nhưng tôi nghĩ vậy ... Nó phải ở đâu đó để ESP/RSP biết đi đâu tiếp theo. Nhưng đây là việc triển khai và phụ thuộc vào hệ điều hành ... –

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