2010-03-31 31 views
49

Trong mã lắp ráp sau đó tôi đổ ra sử dụng objdump:Đăng ký% eiz là gì?

lea 0x0(%esi,%eiz,1),%esi 

là gì đăng ký %eiz? Mã trước có nghĩa là gì?

+1

Bạn có thể tìm thấy http://sourceware.org/ml/binutils/2009-01/msg00081.html thú vị. –

Trả lời

51

Xem Why Does GCC LEA EIZ?:

Rõ ràng %eiz là một giả đăng ký mà chỉ đánh giá bằng không tại mọi thời điểm (như r0 trên MIPS).

...

tôi cuối cùng đã tìm thấy một danh sách gửi thư bưu điện tăng binutils guru Ian Lance Taylor cho thấy các câu trả lời. Đôi khi GCC chèn các lệnh NOP vào luồng mã để đảm bảo căn chỉnh và các công cụ thích hợp như vậy. Lệnh NOP mất một byte, vì vậy bạn sẽ nghĩ rằng bạn chỉ có thể thêm bao nhiêu khi cần thiết. Nhưng theo Ian Lance Taylor, chip nhanh hơn để thực hiện một lệnh dài hơn nhiều lệnh ngắn. Vì vậy, thay vì chèn bảy lệnh NOP, thay vào đó họ sử dụng một LEAR kỳ lạ, sử dụng bảy byte và tương đương ngữ nghĩa với một NOP.

+2

Người thông minh :) Cảm ơn bạn đã trả lời! do đó mã ở trên chỉ là phiên bản dài hơn của nop: P – Heartinpiece

21

(Rất muộn cho trò chơi, nhưng điều này có vẻ như một sự bổ sung thú vị): Nó không phải là một đăng ký nào cả, đó là một dấu ngoặc kép mã hóa lệnh của Intel. Khi sử dụng một byte ModRM để tải từ bộ nhớ, có 3 bit được sử dụng cho trường đăng ký để lưu trữ 8 thanh ghi có thể. Nhưng vị trí mà ESP (con trỏ ngăn xếp) "sẽ" thay vì được bộ vi xử lý giải thích là "một byte SIB theo hướng dẫn này" (nghĩa là chế độ địa chỉ mở rộng, không phải là tham chiếu đến ESP). Vì những lý do chỉ được biết đến với các tác giả, trình biên dịch GNU đã luôn đại diện cho "số không nơi đăng ký này sẽ được" "đăng ký"% eiz ". Cú pháp của Intel chỉ giảm nó.

+1

Cảm ơn bạn đã chia sẻ :) –

12

Andy Ross cung cấp nhiều hơn lý do cơ bản, nhưng không may là sai hoặc ít nhất là khó hiểu về các chi tiết kỹ thuật. Đúng là địa chỉ hiệu quả của chỉ (%esp) không thể được mã hóa chỉ với byte ModR/M thay vì được giải mã là (%esp), nó được sử dụng để báo hiệu rằng một byte SIB cũng được bao gồm. Tuy nhiên, thanh ghi giả %eiz không phải lúc nào cũng được sử dụng với một byte SIB để biểu thị rằng một byte SIB đã được sử dụng.

byte SIB (tỷ lệ/chỉ mục/cơ sở) có ba phần: chỉ số (đăng ký như %eax hoặc %ecx quy mô được áp dụng), tỷ lệ (sức mạnh của hai từ 1 đến 8 rằng thanh ghi chỉ mục được nhân với), và cơ sở (một thanh ghi khác được thêm vào chỉ số được chia tỷ lệ). Đây là những gì cho phép các hướng dẫn như add %al,(%ebx,%ecx,2) (mã máy: 00 04 4b - opcode, modr/m, sib (lưu ý không có đăng ký% eiz mặc dù byte SIB đã được sử dụng)) (hoặc theo cú pháp Intel ", thêm BYTE PTR [ecx * 2 + ebx], al ").

Tuy nhiên, không thể sử dụng %esp làm chỉ mục đăng ký trong byte SIB. Thay vì cho phép tùy chọn này, Intel thay vào đó thêm một tùy chọn để sử dụng thanh ghi cơ sở như không có mở rộng hoặc lập chỉ mục. Do đó để phân biệt giữa trường hợp add %al,(%ecx) (mã máy: 00 01 - opcode, modr/m) và add %al,(%ecx) (mã máy: 00 04 21 - opcode, modr/m, sib), cú pháp thay thế add %al,(%ecx,%eiz,1) được sử dụng thay thế (hoặc cho Intel cú pháp: add BYTE PTR [ecx+eiz*1],al).

Và như được giải thích trong bài viết được Sinan liên kết, hướng dẫn cụ thể này (lea 0x0(%esi,%eiz,1),%esi) chỉ được sử dụng làm nop nhiều byte (tương đương esi = &*esi) để chỉ thực hiện một lệnh nop thay vì nhiều hướng dẫn nop.

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