2009-12-14 24 views
18

Khi trạng thái tiêu đề, tại sao một người dùng "movl $ 1,% eax" chứ không phải, nói " movb $ 1,% eax ", tôi đã nói rằng movl sẽ không ra các bit thứ tự cao của% eax, nhưng không phải là% eax một thanh ghi tương đương với kích thước từ vựng của hệ thống? có nghĩa là movl là trong thực tế một hoạt động số nguyên (và không phải là một dài?)

Tôi rõ ràng là một chút nhầm lẫn về tất cả; Cảm ơn.

Trả lời

3

long ban đầu là 32 bit, trong khi intshort là 16. Và tên của các mã không thay đổi mỗi khi có ai đó đi kèm với hệ điều hành mới.

+1

Phiên bản hệ điều hành có liên quan gì với các quy ước đặt tên? –

+0

Đó là một con số của bài phát biểu. Mục đích là để chỉ ra rằng một khi được xuất bản, đặc tả tập lệnh không bị thay đổi một cách triệt để. –

+0

Đây là lý do tại sao tôi thích cú pháp của Intel đối với cú pháp GAS. Intel: mov dword eax, ecx GAS: movl eax, ecx Toán hạng kích thước "l" gây nhầm lẫn cho mọi người. Nhiều người nhận được rằng 'dword' có nghĩa là 32-bit. – Jason

5

%eax là thanh ghi 32 bit. Để sử dụng chiều rộng nhỏ hơn, bạn cần %ax cho 16 bit. %ax có thể được chia thành %ah cho byte cao là %ax%al cho byte thấp hơn. Cũng vậy với các GPR khác x86.

Nhìn tham chiếu hướng dẫn thiết lập Intel cho lệnh mov, tôi không thấy biến thể có thể di chuyển một byte vào thanh ghi 32 bit - có thể được hiểu là di chuyển vào %al.

movl là hướng dẫn 32 bit, giá trị cho các byte trên sẽ tương ứng với số không trong trường hợp có giá trị tức thời. Nếu bạn di chuyển từ bộ nhớ, bạn sẽ di chuyển toàn bộ từ 32 bit.

%eax không được xóa 0 trừ khi bạn movl $0, %eax hoặc nếu bạn xorl %eax, %eax. Nếu không, nó giữ bất cứ giá trị nào trước đó trong đó. Khi bạn movl $1, %eax, bạn sẽ kết thúc với 0x00000001 trong thanh ghi vì lệnh 32 bit di chuyển giá trị ngay lập tức 32 bit vào thanh ghi.

+0

Lệnh movl đó là hướng dẫn 32 bit một phần là câu trả lời tôi đang tìm kiếm, nhưng một câu trả lời khác mà tôi yêu cầu là liệu mặc định% eax có được _not_ zeroed out, hoặc là undefied không? –

+1

% eax không bao giờ bị xóa trừ khi bạn làm như vậy một cách rõ ràng. Nếu bạn sử dụng movb để chỉ viết vào một trong các byte, các byte khác không thay đổi. –

7

Trên máy 32 bit,% eax là thanh ghi 4 byte (32 bit). movl sẽ ghi vào tất cả 4 byte. Trong ví dụ của bạn, nó sẽ không vượt quá 3 byte trên và đặt 1 vào byte thấp nhất. Movb sẽ chỉ thay đổi byte thứ tự thấp.

+0

Vì vậy, movl là một hoạt động 4 byte? –

+0

Bạn không chắc chắn bộ lắp ráp này là gì, nhưng không phải là sự khác biệt duy nhất kích thước của hằng số? – peterchen

+2

Có. Trong kiến ​​trúc IA32 (thường được gọi là x86), "dài" có nghĩa là 4 byte, và movl là viết tắt của "di chuyển dài". –

1

%eax là 32 bit trên các máy 32 bit. %ax là 16 bit và %ah%al là thành phần cao và thấp 8 bit của nó.

Do đó movl hoàn toàn hợp lệ tại đây. Hiệu quả khôn ngoan, movl sẽ nhanh như movb và không vượt quá 3 byte cao của %eax thường là thuộc tính mong muốn. Bạn có thể muốn sử dụng nó như là một giá trị 32-bit sau đó, vì vậy movb không phải là một cách tốt để di chuyển một byte ở đó.

36

trái ngược với, nói, "movb $ 1,% eax"

hướng dẫn này không hợp lệ. Bạn không thể sử dụng eax với lệnh movb. Thay vào đó, bạn sẽ sử dụng thanh ghi 8 bit. Ví dụ:

movb $ 1, $ al

nhưng không phải là% eax một đăng ký đó là tương đương với kích thước của wordsize của hệ thống?

No. EAX sẽ luôn là giá trị 32 bit, bất kể quy mô đăng ký của hệ thống là bao nhiêu.

Bạn đang gây nhầm lẫn với kích thước biến C với kích thước đăng ký. Kích thước biến C có thể thay đổi tùy thuộc vào hệ thống và trình biên dịch của bạn.

Lắp ráp đơn giản hơn C. Trong lắp ráp GAS, hướng dẫn được gắn các ký tự "b", "s", "w", "l", "q" hoặc "t" để xác định toán hạng kích thước nào đang được thao túng.

* b = byte (8 bit) 
* s = short (16 bit integer) or single (32-bit floating point) 
* w = word (16 bit) 
* l = long (32 bit integer or 64-bit floating point) 
* q = quad (64 bit) 
* t = ten bytes (80-bit floating point) 

Các kích thước này không đổi. Họ sẽ không bao giờ bị thay đổi. al luôn luôn là 8 bit và eax luôn là 32 bit.

+0

Câu trả lời hay, cảm ơn! –

2

Lựa chọn thứ hai của bạn sẽ chỉ tạo ra lỗi, x86 không có hướng dẫn đó. X86 là một chút duy nhất liên quan đến việc tải byte vào một số thanh ghi nhất định. Có, trên hầu hết các kiến ​​trúc bộ lệnh, toán hạng là số không hoặc mở rộng dấu, nhưng x86 cho phép bạn viết chỉ các byte thấp hơn hoặc thấp hơn 16 bit của một số trong số chúng.

Chắc chắn có sự lựa chọn khác, như thanh toán bù trừ thanh ghi và sau đó incrementing nó, nhưng đây là ba lựa chọn ban đầu hợp lý-looking bạn có:

0: b8 01 00 00 00   movl $0x1,%eax 

    5: 31 c0     xorl %eax,%eax 
    7: b0 01     movb $0x1,%al 

    9: b0 01     movb $0x1,%al 
    b: 0f b6 c0    movzbl %al,%eax 

Đầu tiên là 5 byte, thứ hai 4, thứ ba 5. Vì vậy, thứ hai là sự lựa chọn tốt nhất nếu tối ưu hóa cho không gian, nếu không tôi cho rằng một trong những khả năng chạy nhanh nhất là lần đầu tiên. X86 là đường ống dẫn sâu trong những ngày này, do đó, hai hướng dẫn sẽ khóa liên động và máy có thể cần một vài trạng thái chờ tùy thuộc vào chi tiết của phần cứng đường ống.

Tất nhiên, những ops x86 đang được dịch theo nhiều cách CPU cụ thể vào CPU micro-ops, và do đó ai mà biết được điều gì sẽ xảy ra.

+0

Câu trả lời rất hay, rất giải thích. Cảm ơn –

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