2015-11-13 22 views
5

Vì vậy, tôi đã xem xét ILDASM, kiểm tra một .exe mà trông như thế này:Toán tử == chính xác làm gì?

int a = 2; 
Int32 b = 1; 
if(b == 1) 
{ 

} 

Bây giờ, mã CIL trông như thế:

IL_0005: ldloc.1 
IL_0006: ldc.i4.1 
IL_0007: ceq 
IL_0009: ldc.i4.0 
IL_000a: ceq 
IL_000c: stloc.2 

Tôi hiểu rằng đầu tiên b được nạp (được lưu trữ tại [1]), sau đó một hằng số với giá trị là 1 và sau đó chúng được so sánh. Những gì tôi không hiểu là tại sao một hằng số khác với giá trị 0 được nạp và so sánh, trước khi kết quả của so sánh đó được lưu trữ.
Vì so sánh đầu tiên đã tạo ra giá trị chân lý, hãy kiểm tra nếu giá trị này là 0 đảo ngược kết quả, phải không?
Câu hỏi của tôi bây giờ là: tại sao nó bị đảo ngược? Tôi cho rằng nó có liên quan đến toán tử == mà tôi đã sử dụng và lý thuyết của tôi là nó trả về sự khác biệt. Nếu sự khác biệt này là 0, các giá trị là như nhau, do đó, đúng sẽ là kết quả. Nhưng 0 là viết tắt của sai, vì vậy nó cần phải được đảo ngược.
Tôi dường như không thể tìm thấy bất cứ điều gì về chủ đề này, chỉ cần một cái gì đó về các nhà khai thác như == ~ hoặc thích. Hy vọng bạn có thể soi sáng cho tôi :)

Trân trọng

Wilsu

PS: Đây là mã đầy đủ:

.method private hidebysig instance void Form1_Load(object sender, 
               class [mscorlib] 
System.EventArgs e) cil managed 
{ 
// Code size  19 (0x13) 

.maxstack 2 
.locals init ([0] int32 a, 
     [1] int32 b, 
     [2] bool CS$4$0000) 
IL_0000: nop 
IL_0001: ldc.i4.2 
IL_0002: stloc.0 
IL_0003: ldc.i4.1 
IL_0004: stloc.1 
IL_0005: ldloc.1 
IL_0006: ldc.i4.1 
IL_0007: ceq 
IL_0009: ldc.i4.0 
IL_000a: ceq 
IL_000c: stloc.2 
IL_000d: ldloc.2 
IL_000e: brtrue.s IL_0012 
IL_0010: nop 
IL_0011: nop 
IL_0012: ret 
} // end of method Form1::Form1_Load 
+1

Tôi không hiểu điều đó chút nào. Tôi đoán là nó từ một đoạn mã khác. Vui lòng đăng một ví dụ ngắn nhưng * hoàn thành *. –

+0

Tôi nhận được cùng một (ít nhất là kết quả tương tự) chỉ với mã này bên trong chính. – Rob

+0

bạn có đang biên soạn bản phát hành không? (Tôi không thấy bất kỳ "nop", nhưng ...), và: đây có phải là toàn bộ mã * không? Có vẻ như nó đã thực hiện một số thứ tự vui vẻ, p Nhưng: Tôi không thấy biến số thứ 3, vì vậy nó không rõ ràng đối với tôi những gì 'stloc.2' thậm chí * có nghĩa là * ... –

Trả lời

1

Nó đang làm một bước nhảy đến cuối của hàm, theo như tôi có thể tập hợp.

void Main() 
{ 
    int a = 2; 
    Int32 b = 1; 
    if(b == 1) 
    { 
     Console.WriteLine("A"); 
    } 
} 

Cung cấp cho tôi:

IL_0000: nop   
IL_0001: ldc.i4.2  
IL_0002: stloc.0  // a 
IL_0003: ldc.i4.1  
IL_0004: stloc.1  // b 
IL_0005: ldloc.1  // b 
IL_0006: ldc.i4.1  
IL_0007: ceq   
IL_0009: ldc.i4.0  
IL_000A: ceq   
IL_000C: stloc.2  // CS$4$0000 
IL_000D: ldloc.2  // CS$4$0000 
IL_000E: brtrue.s IL_001D 
IL_0010: nop   
IL_0011: ldstr  "A" 
IL_0016: call  System.Console.WriteLine 
IL_001B: nop   
IL_001C: nop   
IL_001D: ret   

Bắt đầu từ IL_0005, ta có:

tải b.
Tải 1.
ceq (Nếu bằng nhau, đẩy 1, nếu sai đẩy 0) - Kết quả ở đây sẽ 1
tải 0
ceq - Kết quả ở đây sẽ 0
brtrue.s IL_001D - Nếu giá trị khác không, nhảy đến IL_001D (cuối chức năng)

Vì vậy, về cơ bản, biên soạn như sau:

int a = 2; 
Int32 b = 1; 
if(!(b == 1)) 
    goto end; 
Console.WriteLine("A"); 
:end 
return; 
+2

cho ngữ cảnh, khi tôi biên dịch (tối ưu hóa) tôi nhận được: 'ldc.i4.1',' ldc.i4.1', 'bne.un.s {thành ret}', 'ldstr" A "', 'call void [mscorlib] System.Console :: WriteLine (chuỗi)', 'ret' - rất khác nhau –

+0

mặc dù thẳng thắn tôi hơi thất vọng vì nó không loại bỏ hoàn toàn và biên dịch thành 'ret', vì so sánh hai hằng số tại thời gian chạy có vẻ ... câm –

+0

Cảm ơn bạn rất nhiều, đó là chính xác những gì tôi muốn biết. – Wilsu

3

ceq lấy hai giá trị từ ngăn xếp và kết quả là 1 nếu chúng được coi là bằng nhau và 0 nếu chúng không giống nhau. Tuy nhiên, cho dù == trong C# kết quả trong ceq phụ thuộc vào rất nhiều thứ:

  • các kiểu dữ liệu
    • là họ primatives?
    • họ có tùy chỉnh == nhà khai thác không?
    • là chúng có tham chiếu không?
  • bối cảnh
    • nó có thể được tối ưu hóa để cái gì khác? (Tôi nhận được bne.un.s trong ví dụ tương tự; cũng có beq*, br*, switch, v.v.)
    • có thể xóa hoàn toàn không?
+0

Về các kiểu dữ liệu: đó là lý do tại sao tôi sử dụng các số nguyên. Các kiểu dữ liệu nguyên thủy, không có toán tử quá tải. Nó không bao giờ vượt qua tâm trí của tôi rằng một cái gì đó như vậy có lẽ đơn giản như các nhà điều hành == có thể được tối ưu hóa thêm nữa ... bạn đã cho tôi quan tâm, tôi sẽ xem xét bất cứ điều gì bne.un.s bây giờ. Cảm ơn bạn đã dành thời gian. – Wilsu

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