2011-11-13 7 views
7

Tôi có một nghi ngờ rất cơ bản ở đây. Tôi có hai mã C rất đơn giản và mã lắp ráp của họ:Trong assembler, tại sao việc sử dụng các thanh ghi khác nhau giữa cộng và trừ?

chương trình 1:

main() 

{ 

    int temp1, temp2, temp3; 
    char temp5, temp6, temp7, temp8, temp9; 
    temp1 = 5; 
    temp1 = 9 - temp1; 
} 

hội:

0x080483b4 <+0>: push ebp  
    0x080483b5 <+1>: mov ebp,esp  
    0x080483b7 <+3>: sub esp,0x20  
    0x080483ba <+6>: mov DWORD PTR [ebp-0xc],0x5  
    0x080483c1 <+13>: mov eax,0x9  
    0x080483c6 <+18>: sub eax,DWORD PTR [ebp-0xc]  
    0x080483c9 <+21>: mov DWORD PTR [ebp-0xc],eax  
    0x080483cc <+24>: leave  
    0x080483cd <+25>: ret 

Chương trình 2:

main()  
{  
    int temp1, temp2, temp3; 
    char temp5, temp6, temp7, temp8, temp9; 
    temp1 = 5; 
    temp1 = 9 + temp1;  
} 

hội:

0x080483b4 <+0>: push ebp  
    0x080483b5 <+1>: mov ebp,esp  
    0x080483b7 <+3>: sub esp,0x20  
    0x080483ba <+6>: mov DWORD PTR [ebp-0xc],0x5  
    0x080483c1 <+13>: add DWORD PTR [ebp-0xc],0x9  
    0x080483c5 <+17>: leave  
    0x080483c6 <+18>: ret 

Tại sao trừ trường hợp phép trừ, đăng ký eax cần được sử dụng và không phải trong trường hợp bổ sung. nó không thể được như:

0x080483c1 <+13>: sub DWORD PTR [ebp-0xc],0x9 

thay vì -

0x080483c1 <+13>: mov eax,0x9 

0x080483c6 <+18>: sub eax,DWORD PTR [ebp-0xc] 
+0

không. Trong mã C, bạn trừ một biến từ 9. Trong hội đồng của bạn, bạn nên trừ một đăng ký từ 9, đó là của mã lắp ráp và không phụ DWORD PTR [ebp-0xc], 0x9 . Trên mã lắp ráp, eax được trừ với 5. Trong tiền đề của bạn, bạn sẽ trừ 5 bằng 9. –

+0

bạn đã biên dịch với các tối ưu hóa được bật chưa? – ninjalj

+0

@ninjalj: Rõ ràng là không. Bởi vì nếu không thì toàn bộ điều chắc chắn sẽ được tối ưu hóa thành một 'lần nữa'. – celtschk

Trả lời

10

Tôi đoán vì Ngoài ra là giao hoán (A + B == B + A), trong khi trừ không phải là (A - B! = B - A). Do việc bổ sung 9 + temp1 giống như temp1 + 9, do đó trình tự lắp ráp đơn giản hơn. 9 - temp1 liên quan đến việc tạo biến tạm thời.

+4

bạn có nghĩa là giao hoán: phương tiện liên kết * (A + B) + C == A + (B + C) * – Christoph

+4

Tôi đã thực sự Cristoph, hai thập kỷ kể từ lớp toán cuối cùng của tôi và hai loại bia giữa này và sau đó. –

2

temp1 = 9 - temp1; giống với temp1 = - temp1 + 9;. Đây thực hiện 2 hoạt động:

  1. phủ nhận temp1
  2. Do việc bổ sung

eax được sử dụng như là vị trí tạm thời để lưu các giá trị trung bình.

Trong trường hợp bổ sung, không có "giá trị trung bình", hoạt động có thể được thực hiện trực tiếp.

+0

Câu trả lời này không giải thích những gì đang được hỏi trong câu hỏi. Ngoài ra, mã assembly không chứa lệnh negation. – Nayuki

2

Lý do thực tế cho hành vi quan sát đã được ngụ ý bởi những câu trả lời khác, nhưng không bao giờ đề cập một cách rõ ràng:

bộ giảng dạy chung đặc trưng ops cho phép tính sau:

%register := %register + $immediate [1] 
%register := %register - $immediate [2] 

Bởi vì giao hoán, [1] cũng có thể được sử dụng để tính

%register := $immediate + %register 

Tuy nhiên, một op chuyên dụng cho

%register := $immediate - %register 

là nói chung không có sẵn, có nghĩa là nó đã được mô phỏng, ví dụ như theo trình tự

%temp  := %register 
%register := $immediate 
%register := %register - %temp 
1

Lý do là thiếu tính đối xứng trong tập lệnh x86, mà không chứa một lệnh trừ số đăng ký từ hằng số.

Ví dụ: bộ lệnh ARM chứa lệnh RSB (Đảo ngược giá trị) chính xác cho mục đích này.

+0

Trên thực tế, bộ lệnh ARM là không đối xứng trong trường hợp này - nó thiếu một lệnh 'reverse add' (vô dụng), trong đó x86 trong trường hợp này là đối xứng - thiếu cả hai lệnh, phép trừ ngược hữu ích và bổ sung ngược vô dụng . Lý do sâu sắc hơn cho điều này (và nhu cầu cho một phụ ngược lại) tất nhiên là thiếu tính đối xứng trong phép trừ - nó không giao hoán. – hirschhornsalz

+0

Tính đối xứng trong trường hợp này là giữa hai cách để thực hiện phép trừ. – starblue

+1

Ngẫu nhiên, vi điều khiển thương hiệu PIC có lệnh 'trừ W từ hằng số', nhưng không trừ 'hằng số từ thanh ghi W', vì lệnh sau có thể được mô phỏng bằng cách thêm 256 hằng số. – supercat