2012-05-09 21 views
9

Tôi đang làm việc trên một phần rất thấp của ứng dụng trong đó hiệu suất là rất quan trọng.Tại sao các lệnh lắp ráp lại chứa các phép nhân trong lệnh "lea"?

Trong khi điều tra lắp ráp tạo ra, tôi nhận thấy các hướng dẫn sau đây:

lea eax,[edx*8+8] 

Tôi thường thấy bổ sung khi sử dụng tài liệu tham khảo bộ nhớ (ví dụ [edx + 4]), nhưng đây là lần đầu tiên tôi nhìn thấy một phép nhân.

  • Điều này có nghĩa là bộ xử lý x86 có thể thực hiện phép nhân đơn giản trong lệnh lea?
  • Phép nhân này có ảnh hưởng đến số chu kỳ cần thiết để thực hiện lệnh không?
  • Phép nhân được giới hạn ở lũy thừa 2 (tôi có giả định đây là trường hợp) không?

Xin cảm ơn trước.

+5

Hãy lưu ý cách nó nhân với sức mạnh của hai người. – Mysticial

+0

Xem thêm [Mục đích của hướng dẫn LEA là gì?] (Https://stackoverflow.com/questions/1658294/whats-the-purpose-of-the-lea-instruction) để biết thêm thông tin chung về việc sử dụng nó cho những thứ khác hơn là tính toán địa chỉ nghiêm ngặt. –

Trả lời

11

Để mở rộng nhận xét của tôi và trả lời phần còn lại của câu hỏi ...

Có, giới hạn ở hai quyền. (2, 4, và 8 cụ thể) Vì vậy, không có số nhân là cần thiết vì nó chỉ là một sự thay đổi. Điểm của nó là để nhanh chóng tạo ra một địa chỉ từ một biến chỉ mục và một con trỏ - nơi mà kiểu dữ liệu là một từ đơn giản 2, 4 hoặc 8 byte. (Mặc dù nó thường bị lạm dụng cho các mục đích sử dụng khác.)

Đối với số chu kỳ cần thiết: Theo Agner Fog's tables, có vẻ như lệnh lea không đổi trên một số máy và biến trên các máy khác.

Trên Sandy Bridge có hình phạt 2 vòng nếu đó là "liên quan phức tạp hoặc rip". Nhưng nó không nói những gì "phức tạp" có nghĩa là ... Vì vậy, chúng tôi chỉ có thể đoán trừ khi bạn làm một điểm chuẩn.

+0

Cảm ơn. Cũng thích các tham chiếu đến Agner Fog (mặc dù các liên kết trong câu trả lời của bạn doesnt 'có vẻ là chính xác). – Patrick

+0

Rất tiếc, sao chép sai + dán. Đã sửa lỗi. – Mysticial

+0

@Mysticial - AFAIK, đây không phải là 'lea' cụ thể. Kiểm tra câu trả lời của tôi :) – ArjunShankar

8

Thực ra, đây không phải là điều gì đó cụ thể đối với hướng dẫn lea.

Loại địa chỉ này được gọi là Scaled Addressing Mode. Các nhân được thực hiện bằng một sự thay đổi chút, đó là tầm thường:

A Left Shift

Bạn có thể làm 'quy mô giải quyết' với một mov quá, ví dụ (lưu ý rằng đây không phải là hoạt động tương tự, sự giống nhau duy nhất là thực tế là ebx*4 đại diện cho một nhân địa chỉ):

mov edx, [esi+4*ebx] 

(nguồn: http://www.cs.virginia.edu/~evans/cs216/guides/x86.html#memory)

Đối với một danh sách đầy đủ hơn, hãy xem this Intel document. Bảng 2-3 cho thấy rằng một tỷ lệ 2, 4, hoặc 8 được cho phép. Không có gì khác.

Độ trễ (về số lượng chu kỳ): Tôi không nghĩ rằng điều này sẽ bị ảnh hưởng. Một sự thay đổi là một vấn đề của các kết nối, và lựa chọn giữa ba ca có thể là vấn đề của 1 giá trị trễ của bộ ghép kênh.

+1

'mov' đó nhận được ** nội dung ** của bộ nhớ tại địa chỉ" được tạo ", trong khi' lea' nhận địa chỉ ** được tạo "** – ninjalj

+0

@ninjalj - Vấn đề là * không * những gì các mov, nhưng thực tế là 'thu nhỏ địa chỉ' (tức là con trỏ toán liên quan đến nhân một con trỏ bằng 2,4,8) là không cụ thể cho 'lea'. – ArjunShankar

+0

@ninjalj - Và vì nó xuất hiện với tôi rằng đó là từ ngữ của phần đó trong câu trả lời của tôi mà có phần mơ hồ, tôi đã giải thích 'mov' hơi tốt hơn bây giờ. Cảm ơn. – ArjunShankar

6

Để mở rộng về câu hỏi cuối cùng của bạn:

Sản phẩm nhân giới hạn quyền hạn của 2 (Tôi sẽ giả định đây là trường hợp)?

Lưu ý rằng bạn sẽ có được kết quả của base + scale * index, như vậy trong khi scale phải là 1, 2, 4 hoặc 8 (kích thước của kiểu dữ liệu x86 số nguyên), bạn có thể nhận được tương đương với một nhân bởi một số hằng số khác nhau bằng cách sử dụng cùng một thanh ghi như baseindex, ví dụ:

lea eax, [eax*4 + eax] ; multiply by 5 

này được sử dụng bởi trình biên dịch để làm giảm sức mạnh, ví dụ: cho một phép nhân bằng 100, tùy thuộc vào tùy chọn trình biên dịch (model CPU mục tiêu, lựa chọn tối ưu hóa), bạn có thể nhận được:

lea (%edx,%edx,4),%eax ; eax = orig_edx * 5 
lea (%eax,%eax,4),%eax ; eax = eax * 5 = orig_edx * 25 
shl $0x2,%eax   ; eax = eax * 4 = orig_edx * 100 
+1

Xem câu hỏi SO này: http://stackoverflow.com/questions/6120207/imul-or-shift-instruction vì sao bạn nên để giảm độ mạnh cho trình biên dịch. – ninjalj

+1

+1, tôi thích câu trả lời thứ hai về câu hỏi được liên kết đó. :) – Mysticial