2010-01-25 28 views
25

tôi đang tìm kiếm thông qua các disassmbly của chương trình của tôi (vì nó đã bị rơi), và nhận thấy rất nhiềuTại sao Visual Studio sử dụng xchg rìu, rìu

xchg ax, ax 

Tôi googled nó và phát hiện ra đó là bản chất là một nop, nhưng tại sao phòng thu trực quan làm một xchg thay vì một noop?

Ứng dụng này là một C# .NET3.5 64-bit ứng dụng, biên soạn bởi visual studio

+1

là các byte được liên kết với các hướng dẫn này giống nhau không? nop nên được hex 90. là xchg axe, ax một hướng dẫn 2 byte? –

+0

Điều này hóa ra lại là một câu hỏi có chút sắc thái hơn tôi nghĩ ban đầu (hoặc vẫn nhớ). –

+0

hey bạn có thể cho tôi biết làm thế nào để nhìn vào mã lắp ráp như của bạn. tôi muốn xem làm thế nào một prgoram đơn giản được chuyển đổi để lắp ráp. thanks – masfenix

Trả lời

33

Trên x86 các NOP hướng dẫn XCHG AX, AX

2 hướng dẫn ghi nhớ lắp ráp đến Bơm này cực kỳ nhị phân tương tự mã. (Thực ra, tôi cho rằng một người lắp ráp có thể sử dụng bất kỳ xchg của một thanh ghi nào, nhưng AX hoặc EAX là những gì thường được sử dụng cho số nop theo như tôi biết).

xchg ax, ax có các thuộc tính thay đổi không có giá trị đăng ký và thay đổi không có cờ (hey - đó là không có op!).


Sửa (để đáp lại một lời nhận xét bởi Anon.):

Oh đúng - bây giờ tôi nhớ có một số mã hóa cho các hướng dẫn xchg. Một số có một bộ mod/r/m bit (giống như nhiều hướng dẫn kiến ​​trúc Intel x86) chỉ định nguồn và đích. Những mã hóa này có nhiều hơn một byte. Ngoài ra còn có một mã hóa đặc biệt sử dụng một byte đơn và trao đổi một thanh ghi mục đích chung với (E)AX. Nếu thanh ghi được chỉ định cũng là (E)AX, bạn có lệnh NOP một byte. bạn cũng có thể chỉ định rằng (E)AX được trao đổi với chính nó bằng cách sử dụng biến thể lớn hơn của lệnh xchg.

Tôi đoán rằng MSVC sử dụng phiên bản nhiều byte xchg với nguồn và đích khi muốn nhai nhiều hơn một byte không hoạt động - phải mất cùng một số chu kỳ như một byte xchg , nhưng sử dụng nhiều không gian hơn. Trong quá trình tháo gỡ, bạn sẽ không thấy nhiều byte xchg được giải mã dưới dạng NOP, ngay cả khi kết quả giống nhau.

Cụ thể xchg eax, eax hoặc nop có thể được mã hóa dưới dạng mã vạch 0x90 hoặc 0x87 0xc0 tùy thuộc vào việc bạn có muốn sử dụng hết 1 hoặc 2 byte hay không. Trình tách Visual Studio (và có thể là những người khác) sẽ giải mã mã opcode 0x90 làm hướng dẫn NOP và sẽ giải mã opcode 0x87 0xc0xchg eax, eax.

Nó được một lúc kể từ khi tôi đã thực hiện công việc ngôn ngữ lắp ráp chi tiết, vì vậy rất có thể là tôi sai trên ít nhất một số ở đây ...

+0

Vậy tại sao tôi cũng thấy nop? – Malfist

+0

Đó sẽ là bộ tách rời thông minh (hoặc câm, tùy thuộc vào những gì bạn muốn nó làm). Bạn có thấy cả hai giải mã bằng cách sử dụng cùng một bộ tách rời? Đó có thể là một cái gì đó thú vị để xem xét. –

+0

Đó là bộ tách hình ảnh trực quan ... – Malfist

8

xchg ax,axnop thực sự là lệnh tương tự, họ ánh xạ cùng một opcode (0x90 iirc). Được rồi, xchg ax,ax một Không có Op. Tại sao một người nên lãng phí mã hóa opcode thêm với các hướng dẫn không làm gì?

Có vấn đề là lý do tại sao bạn thấy cả hai bản ghi nhớ được in.Tôi đoán nó chỉ là một lỗ hổng trong tháo gỡ của bạn, không có sự khác biệt nhị phân.

+1

0x90 không 90 ... .. – Earlz

+0

Câu hỏi về việc có lãng phí mã hóa mã hóa opcode trên các lệnh không có gì làm tăng một số vấn đề thú vị, đặc biệt là trong các kiến ​​trúc được chỉ định để bẫy các lệnh không hợp lệ. Một mặt, nếu một phần đáng kể không gian opcode được sử dụng bởi các lệnh giống hệt nhau về mặt chức năng, hãy cấm sử dụng tất cả nhưng một mã hóa như vậy sẽ làm cho những người khác có sẵn cho các hoạt động trong tương lai. Mặt khác, làm như vậy có thể làm cho một số kịch bản tạo mã động trở nên khó khăn hơn và nếu các opcodes không hợp lệ được cho là bị mắc kẹt, cần thêm phần cứng để bẫy chúng. – supercat

+0

@supercat: Đó là một chút khác biệt so với chỉ giảm để xác định * nhưng một opcode khác không làm gì, phải không? – SamB

4

MSVC đặt NOP trong mã được biên dịch để xây dựng các bản sửa lỗi, nói chung. Điều này cho phép Chỉnh sửa & Tiếp tục hoạt động.

5

Thực ra, xchg ax,ax chỉ là cách MS ngắt kết nối "66 90". 66 là ghi đè kích thước toán hạng, vì vậy nó được cho là hoạt động trên ax thay vì eax. Tuy nhiên, CPU vẫn thực hiện nó như là một nop. Tiền tố 66 được sử dụng ở đây để làm cho lệnh có kích thước hai byte, thường là cho các mục đích căn chỉnh.

+0

cũng có nhiều NOP khác với kích thước khác nhau và trình biên dịch có thể chọn một phù hợp nhất http://stackoverflow.com/ a) 12564044/995714 –

2

Tôi không biết nó có liên quan gì đến câu hỏi hay không nhưng nhiều chức năng Windows bắt đầu bằng MOV EDI, EDI. Đó cũng là NOP 2 byte. Hai byte NOP rất hữu ích cho mã hotpatch, bởi vì bạn có thể thay thế nó một cách an toàn bằng một JMP ngắn.

Tham chiếu: http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx

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