2009-02-14 44 views
8

Chuỗi công cụ GCC sử dụng cú pháp lắp ráp AT & T theo mặc định, nhưng hỗ trợ cho cú pháp Intel có sẵn thông qua chỉ thị .intel_syntax.Cách sử dụng hằng số địa chỉ trong cấu trúc nội tuyến GCC x86

Thêm vào đó, cả AT & T và Intel cú pháp có sẵn trong một và một phiên bản prefixnoprefix, mà khác nhau về dù có hoặc không đòi hỏi tiền tố đăng ký tên với một sigil %.

Tùy thuộc vào chỉ thị nào có mặt, định dạng cho hằng số địa chỉ thay đổi.

Hãy xem xét đoạn code C sau

*(int *)0xdeadbeef = 0x1234; 

Sử dụng objdump -d, chúng tôi thấy rằng nó được biên dịch để hướng dẫn lắp ráp sau

movl $0x1234,0xdeadbeef 

Vì không có đăng ký tham gia, đây là cú pháp chính xác cho cả hai .att_syntax prefix.att_syntax noprefix, nghĩa là. được nhúng trong mã C, chúng trông giống như thế này

__asm__(".att_syntax prefix"); 
__asm__("movl $0x1234,0xdeadbeef"); 

__asm__(".att_syntax noprefix"); 
__asm__("movl $0x1234,0xdeadbeef"); 

Bạn có thể tùy chọn bao quanh hằng số địa chỉ bằng dấu ngoặc đơn, ví dụ:

__asm__("movl $0x1234,(0xdeadbeef)"); 

cũng sẽ hoạt động.

Khi thêm một sigil để một hằng địa chỉ đơn giản, mã sẽ không copile

__asm__("movl $0x1234,$0xdeadbeef"); // won't compile 

Khi xung quanh biểu thức này với ngoặc đơn, trình biên dịch sẽ phát ra sai mã mà không báo trước, tức là

__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work! 

Điều này sẽ phát ra không chính xác hướng dẫn

movl $0x1234,0x0 

Trong Intel m ode, hằng số địa chỉ phải được đặt trước bằng một thanh ghi phân đoạn cũng như kích thước toán hạng và cờ PTR nếu có thể có sự mơ hồ. Trên máy tính của tôi (máy tính xách tay lõi kép Intel với Windows XP và các phiên bản MinGW và Cygwin GCC hiện tại), thanh ghi ds được sử dụng theo mặc định.

Dấu ngoặc vuông xung quanh hằng số là tùy chọn. Hằng số địa chỉ cũng được nhận dạng đúng nếu thanh ghi phân đoạn bị bỏ qua, nhưng các dấu ngoặc có mặt. Tuy nhiên, việc bỏ qua thanh ghi sẽ phát ra cảnh báo trên hệ thống của tôi.

Ở chế độ prefix, thanh ghi phân khúc phải được bắt đầu bằng %, nhưng chỉ sử dụng dấu ngoặc đơn sẽ vẫn hoạt động. Đây là những cách khác nhau để tạo ra các hướng dẫn chính xác:

__asm__(".intel_syntax noprefix"); 
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234"); 
__asm__("mov DWORD PTR ds:[0xdeadbeef],0x1234"); 
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns! 

__asm__(".intel_syntax prefix"); 
__asm__("mov DWORD PTR %ds:0xdeadbeef,0x1234"); 
__asm__("mov DWORD PTR %ds:[0xdeadbeef],0x1234"); 
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns! 

Bỏ cả hai phân khúc đăng ký và dấu ngoặc sẽ thất bại để biên dịch

__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); // won't compile 

Tôi sẽ đánh dấu câu hỏi này như wiki cộng đồng, vì vậy nếu bạn có bất cứ điều gì hữu ích để thêm, cảm thấy tự do để làm như vậy.

+0

Đó rõ ràng là không * chỉ * AS trong toolchain đây; (Các) phiên bản nào của gcc có liên quan? Bạn đã kiểm tra đầu ra của gcc -S để xác nhận rằng những gì đang được đưa vào GNU như là những gì bạn mong đợi? –

+0

ok, đó là tôi đã làm rối tung - ít nhất là một phần; thay thế '($ 0xdeadbeaf)' với '0xdeadbeaf' dường như hoạt động; Tôi sẽ chỉnh sửa câu hỏi sau khi thử nghiệm ... – Christoph

+0

@Charles: yes, 'gcc -S' mang lại kết quả mong đợi – Christoph

Trả lời

4

Chỉ thị noprefix/prefix chỉ kiểm soát xem người đăng ký có yêu cầu tiền tố % (*) (ít nhất có vẻ như vậy và đó là sự khác biệt duy nhất trong tài liệu đề cập). Giá trị literal luôn cần tiền tố $ trong cú pháp AT & T và không bao giờ trong cú pháp của Intel. Vì vậy, các công trình sau đây:

__asm__(".intel_syntax prefix"); 
__asm__("MOV [DWORD PTR 0xDEADBEEF], 0x1234"); 

Nếu bạn đang thực sự có khuynh hướng sử dụng Intel lắp ráp cú pháp inline trong mã C biên soạn với GCC và lắp ráp với GAS, đừng quên còn thêm dòng sau sau nó, vì vậy mà các nhà lắp ráp có thể grok phần còn lại của (AT & T cú pháp) lắp ráp được tạo ra bởi GCC:

__asm__(".att_syntax prefix"); 

lý do tôi thấy cho sự phân biệt tiền tố/noprefix được, mà cho AT & cú pháp T, tiền tố % là không thực sự cần thiết cho đăng ký trên kiến ​​trúc Intel, bởi vì các thanh ghi được đặt tên. Nhưng đối với tính đồng nhất, nó có thể có bởi vì một số kiến ​​trúc khác (ví dụ: SPARC) đã được đăng ký số, trong trường hợp chỉ định một số thấp sẽ không rõ ràng về việc địa chỉ bộ nhớ hay đăng ký có nghĩa là gì.

1

Dưới đây là kết quả của riêng tôi:

*(int *)0xdeadbeaf = 0x1234; // reference implementation 

// AT&T: addresses without sigil; parentheses are optional 

__asm__(".att_syntax prefix"); 
__asm__("movl $0x1234,0xdeadbeaf");  // works 
__asm__("movl $0x1234,(0xdeadbeaf)"); // works 
__asm__("movl $0x1234,($0xdeadbeaf)"); // doesn't work, doesn't warn! 
//__asm__("movl $0x1234,$0xdeadbeaf"); // doesn't compile 
//__asm__("movl 0x1234,0xdeadbeaf"); // doesn't compile 
//__asm__("movl 0x1234,(0xdeadbeaf)"); // doesn't compile 

__asm__(".att_syntax noprefix"); 
// same as above: no registers used! 

// Intel: addresses with square brackets or segment register prefix 
// brackets without prefix will warn 

__asm__(".intel_syntax noprefix"); 
__asm__("mov DWORD PTR ds:0xdeadbeaf,0x1234");  // works 
__asm__("mov DWORD PTR ds:[0xdeadbeaf],0x1234"); // works 
__asm__("mov DWORD PTR [0xdeadbeaf],0x1234");  // works, but warns! 
//__asm__("mov DWORD PTR 0xdeadbeaf,0x1234");  // doesn't compile 

// `prefix` will add % to register names 

__asm__(".intel_syntax prefix"); 
__asm__("mov DWORD PTR %ds:0xdeadbeaf,0x1234");  // works 
__asm__("mov DWORD PTR %ds:[0xdeadbeaf],0x1234"); // works 
__asm__("mov DWORD PTR [0xdeadbeaf],0x1234");  // works, but warns! 
//__asm__("mov DWORD PTR 0xdeadbeaf,0x1234");  // doesn't compile 

__asm__(".att_syntax prefix"); 
+0

Như tôi đã lưu ý trong câu trả lời của tôi, tôi không nghĩ rằng noprefix và tiền tố bất kỳ khác nhau về vấn đề này. Các tài liệu chỉ cho biết nó ảnh hưởng đến% ở phía trước của tên đăng ký. Vì vậy, cùng một khối dưới noprefix nên làm việc theo tiền tố quá. –

+0

@ Tom: không may, đó không phải là trường hợp - 'cái phiên bản noprefix' sẽ phát ra một "Lỗi: Bất ngờ thẻ':'" khi được sử dụng với' prefix' – Christoph

+0

@ Tom: phiên bản mà phát ra một cảnh báo sẽ làm việc, mặc dù .. – Christoph

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