“Rep; nop; ” nghĩa là trong x86 assembly? Nó có giống với hướng dẫn "tạm dừng" không?


86
  • Nghĩa rep; noplà gì?
  • Nó có giống như pausehướng dẫn không?
  • Nó có giống với rep nop(không có dấu chấm phẩy) không?
  • Sự khác biệt đối với nophướng dẫn đơn giản là gì?
  • Nó có hoạt động khác nhau trên bộ xử lý AMD và Intel không?
  • (bonus) Tài liệu chính thức cho những hướng dẫn này ở đâu?

Động lực cho câu hỏi này

Sau một số cuộc thảo luận trong phần nhận xét của một câu hỏi khác , tôi nhận ra rằng tôi không biết điều gì rep; nop;có nghĩa là trong assembly x86 (hoặc x86-64). Và tôi cũng không thể tìm thấy một lời giải thích tốt trên web.

Tôi biết đó replà một tiền tố có nghĩa là "lặp lại các lần hướng dẫn tiếp theo cx" (hoặc ít nhất nó là, trong hợp ngữ x86 16 bit cũ). Theo đó bảng tóm tắt ở Wikipedia , nó dường như repchỉ có thể được sử dụng với movs, stos, cmps, lods, scas(nhưng có lẽ hạn chế này đã được gỡ bỏ trên bộ vi xử lý mới hơn). Vì vậy, tôi sẽ nghĩ rep nop(không có dấu chấm phẩy) sẽ lặp lại một lần nophoạt động cx.

Tuy nhiên, sau khi tìm kiếm thêm, tôi càng bối rối hơn. Có vẻ như nó rep; noppause ánh xạ tới cùng một opcode , và pausecó một chút hành vi khác với chỉ nop. Một số thư cũ từ năm 2005 nói những điều khác nhau:

  • "cố gắng không đốt cháy quá nhiều điện"
  • "nó tương đương với 'nop' chỉ với mã hóa 2 byte."
  • "Đó là phép thuật theo thông tin. Nó giống như 'không nhưng hãy để anh chị em HT khác chạy'"
  • "nó tạm dừng trên intel và đệm nhanh trên Athlon"

Với những ý kiến ​​khác nhau, tôi không thể hiểu ý nghĩa chính xác.

Nó đang được sử dụng trong nhân Linux (trên cả i386x86_64 ), cùng với nhận xét này: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */Nó cũng đang được sử dụng trong BeRTOS , với nhận xét tương tự.


Câu trả lời:


75

rep; nopthực sự giống như pausehướng dẫn (opcode F390). Nó có thể được sử dụng cho các nhà lắp ráp chưa hỗ trợ pausehướng dẫn. Trên các bộ xử lý trước, điều này chỉ đơn giản là không làm gì, chỉ giống như nopnhưng trong hai byte. Trên các bộ xử lý mới hỗ trợ siêu phân luồng, nó được sử dụng như một gợi ý cho bộ xử lý rằng bạn đang thực hiện spinloop để tăng hiệu suất. Từ tham chiếu hướng dẫn của Intel :

Cải thiện hiệu suất của các vòng quay chờ quay. Khi thực hiện “vòng lặp chờ quay vòng”, bộ xử lý Pentium 4 hoặc Intel Xeon phải chịu một hình phạt hiệu suất nghiêm trọng khi thoát khỏi vòng lặp vì nó phát hiện có thể vi phạm thứ tự bộ nhớ. Lệnh TẠM DỪNG cung cấp một gợi ý cho bộ xử lý rằng chuỗi mã là một vòng lặp chờ quay vòng. Bộ xử lý sử dụng gợi ý này để tránh vi phạm thứ tự bộ nhớ trong hầu hết các tình huống, giúp cải thiện đáng kể hiệu suất của bộ xử lý. Vì lý do này, bạn nên đặt lệnh TẠM DỪNG trong tất cả các vòng quay chờ.


4
vòng lặp spin-chờ đợi giống như vòng lặp bận rộn-chờ đợi ? "Cải tiến" này chỉ áp dụng cho bộ xử lý siêu phân luồng? (và tại sao?)
Denilson Sá Maia

11
Có, vòng lặp spin-wait cũng giống như vòng lặp chờ đợi. Lợi ích này cũng áp dụng cho các CPU không hỗ trợ siêu phân luồng. Nó có thể được coi là hạn chế số lượng hướng dẫn (không cần thiết) trong các đường ống (chứ không phải cố gắng làm nhiều lần lặp của vòng lặp song song)
Brendan

1
@Brendan, cảm ơn! Tôi đã không hiểu gì cả, cho đến khi bạn nói điều về các lần lặp lại của vòng lặp song song.
GS Falken

11
@Brendan, Ồ, giờ tôi hiểu rồi! Các bộ vi xử lý hiện đại này là superscalar , và do đó chúng sẽ cố gắng chạy nhiều lệnh cùng một lúc. Nếu đây là vòng lặp bận-đợi, việc chạy thêm hướng dẫn sẽ không làm cho nó nhanh hơn, vì nó chỉ đang đợi một điều kiện khác.
Denilson Sá Maia

1
@Denilson: Đúng vậy, tính thân thiện với siêu phân luồng (hoặc chỉ tiết kiệm điện mà không có HT) là một lợi ích lớn, nhưng lợi ích khác là tránh suy đoán sai thứ tự bộ nhớ khi rời khỏi vòng quay. Nếu không pause, vòng quay của bạn sẽ chậm hơn một cách rõ ràng để nhận thấy sự thay đổi trạng thái của vị trí bộ nhớ được ghi bởi một lõi khác.
Peter Cordes

14

rep nop= F3 90 = mã hóa pause, cũng như cách nó giải mã trên các CPU cũ hơn không hỗ trợ pause.


Các tiền tố (khác với lock) không áp dụng cho một lệnh sẽ bị các CPU hiện có bỏ qua trên thực tế.

Tài liệu cho biết việc sử dụng repvới các hướng dẫn mà nó không áp dụng là "dành riêng và có thể gây ra hành vi không thể đoán trước" vì các CPU trong tương lai có thể nhận ra nó như là một phần của một số lệnh mới. Khi họ thiết lập bất kỳ mã hóa lệnh mới cụ thể nào bằng cách sử dụng f3 xx, họ ghi lại cách nó chạy trên các CPU cũ hơn. (Đúng vậy, không gian opcode x86 bị ​​giới hạn đến mức chúng làm những thứ điên rồ như thế này và vâng, nó làm cho bộ giải mã trở nên phức tạp.)

Trong trường hợp này, nó có nghĩa là bạn có thể sử dụng pausetrong các spinloop mà không làm hỏng tính toán ngược . Các CPU cũ không biết về pausenó sẽ giải mã nó thành NOP mà không gây hại gì, như được đảm bảo bởi mục nhậppause thủ công ISA của Intel . Trên các CPU mới, bạn nhận được lợi ích của việc tiết kiệm điện năng / thân thiện với HT và tránh suy đoán sai thứ tự bộ nhớ khi bộ nhớ bạn đang quay thay đổi và bạn rời khỏi vòng quay.


Các liên kết đến sách hướng dẫn của Intel và rất nhiều thứ hay ho khác trên trang thông tin wiki thẻ x86

Một trường hợp khác của reptiền tố vô nghĩa trở thành lệnh mới trên các CPU mới: lzcntF3 0F BD /r. Trên các CPU không hỗ trợ lệnh đó (thiếu cờ tính năng LZCNT trong CPUID của chúng), nó giải mã bằng rep bsr, chạy giống như bsr. Vì vậy, trên các CPU cũ, nó tạo ra 32 - expected_resultvà không được xác định khi đầu vào là 0.

Nhưng tzcntbsflàm điều tương tự với các đầu vào khác 0, vì vậy các trình biên dịch có thể và sử dụng tzcntngay cả khi không đảm bảo rằng CPU mục tiêu sẽ chạy nó như tzcnt. CPU AMD có nhanh tzcnt, chậm bsfvà trên Intel thì cả hai đều nhanh. Miễn là nó không quan trọng về tính đúng đắn (bạn không dựa vào cài đặt cờ hoặc để lại hành vi không được sửa đổi đích trong trường hợp đầu vào = 0), việc giải mã nó như tzcnttrên các CPU hỗ trợ nó sẽ hữu ích.


Một trường hợp reptiền tố vô nghĩa có thể sẽ không bao giờ giải mã khác: rep retđược sử dụng theo mặc định bởi gcc khi nhắm mục tiêu các CPU "chung chung" (tức là không nhắm mục tiêu một CPU cụ thể có -marchhoặc -mtunevà không nhắm mục tiêu AMD K8 hoặc K10.) Sẽ mất nhiều thập kỷ trước bất kỳ ai có thể tạo ra một CPU giải mã rep retnhư bất cứ thứ gì khác ret, bởi vì nó có mặt trong hầu hết các tệp nhị phân trong hầu hết các bản phân phối Linux. Xem `rep ret` nghĩa là gì?


3
Các reptiền tố cũng được sử dụng bởi Intel để thêm khóa sự bỏ bớt.
Paul A. Clayton

Các tiền tố không áp dụng cho một chỉ dẫn sẽ bị bỏ qua. Nhưng có đề cập rằng Tiền tố Lặp lại ( F2HF3H) Được bảo lưu và có thể dẫn đến hành vi không thể đoán trước trong Bảng 11-3. Ảnh hưởng của tiền tố đối với Hướng dẫn SSE, SSE2 và SSE3 . Vì vậy, ứng dụng tiền tố bị bỏ qua đối với một số hướng dẫn, không phải cho tất cả. Vậy tính năng này có được coi là không có giấy tờ không?
St.Antario

2
@ St.Antario: Họ diễn đạt theo cách đó vì các CPU trong tương lai có thể nhận ra nó như một phần của một số lệnh mới. Trên tất cả các CPU thực là trường hợp này, và khi họ thiết lập một mã hóa bằng cách sử dụng, f3 xxhọ sẽ ghi lại cách nó chạy trên các CPU cũ hơn.
Peter Cordes

1
Các tiền tố (trừ khóa) không áp dụng cho một lệnh sẽ bị các CPU hiện có bỏ qua trên thực tế. Nó được ghi lại rằng rep movbenguyên nhân #UD, vì vậy repkhông phải lúc nào cũng bị bỏ qua. Ngay cả khi nó không áp dụng cho một hướng dẫn theo nghĩa như nó được chỉ định trong REP/REPE/REPZ/REPNE/REPNZmục nhập thủ công.
St.Antario

2
@ St.Antario: Thật thú vị! Nói chung, đối với các hướng dẫn cũ hơn, các tiền tố không thể áp dụng được bỏ qua. Khi giới thiệu một hướng dẫn mới, có thể thêm các quy tắc chặt chẽ hơn nếu họ chọn. IDK tại sao họ lại chọn điều đó cho trường hợp cụ thể này.
Peter Cordes
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.