2013-10-24 18 views
9

tôi đã viết chương trình sau đây:Tại sao sử dụng JLE thay vì JL?

#include <stdio.h> 

int main() 
{ 
    int i = 0; 
    for (; i < 4; i++) 
    { 
     printf("%i",i); 
    } 

    return 0; 
} 

tôi biên soạn nó bằng cách sử gcc test.c -o test.o, sau đó tháo rời nó bằng cách sử objdump -d -Mintel test.o. Mã lắp ráp tôi (ít nhất là một phần liên quan) là như sau:

0804840c <main>: 
804840c: 55      push ebp 
804840d: 89 e5     mov ebp,esp 
804840f: 83 e4 f0    and esp,0xfffffff0 
8048412: 83 ec 20    sub esp,0x20 
8048415: c7 44 24 1c 00 00 00 mov DWORD PTR [esp+0x1c],0x0 
804841c: 00 
804841d: eb 19     jmp 8048438 <main+0x2c>   
804841f: 8b 44 24 1c    mov eax,DWORD PTR [esp+0x1c] 
8048423: 89 44 24 04    mov DWORD PTR [esp+0x4],eax 
8048427: c7 04 24 e8 84 04 08 mov DWORD PTR [esp],0x80484e8 
804842e: e8 bd fe ff ff   call 80482f0 <[email protected]> 
8048433: 83 44 24 1c 01   add DWORD PTR [esp+0x1c],0x1 
8048438: 83 7c 24 1c 03   cmp DWORD PTR [esp+0x1c],0x3 
804843d: 7e e0     jle 804841f <main+0x13> 
804843f: b8 00 00 00 00   mov eax,0x0 
8048444: c9      leave 
8048445: c3      ret 

tôi nhận thấy rằng, mặc dù hoạt động so sánh của tôi là i < 4, mã lắp ráp là (sau khi tháo dỡ) i <= 3. Tại sao điều đó lại xảy ra? Tại sao nó sử dụng JLE thay vì JL?

+3

Đó có thể là mã-gen khuyến khích tối ưu hóa tiếp theo, chẳng hạn như bỏ vòng lặp. Điều gì đã không xảy ra, tránh nhìn vào mã không được tối ưu hóa. –

+0

Đây thực sự là lựa chọn tạo mã gcc (bạn cần đào sâu vào biểu diễn cây của mã), nhưng nó biến một phép thử 'var Petesh

Trả lời

5

Vòng lặp đếm ngược lên và có giới hạn không đổi, rất phổ biến. Trình biên dịch có hai tùy chọn để thực hiện kiểm tra chấm dứt vòng lặp - JLEJL. Trong khi hai cách có vẻ hoàn toàn tương đương, hãy xem xét những điều sau đây.

Như bạn có thể thấy trong danh sách tháo gỡ, hằng số (3 trong trường hợp của bạn) được mã hóa thành 1 byte. Nếu vòng lặp của bạn được tính là 256 thay vì 4, nó sẽ là impossible để sử dụng mã hóa hiệu quả như vậy cho lệnh CMP và trình biên dịch sẽ phải sử dụng mã hóa "lớn hơn". Vì vậy, JLE cung cấp một sự cải thiện biên trong mật độ mã (mà là cuối cùng tốt cho hiệu suất vì bộ nhớ đệm).

0

Nó sẽ JLE vì nó chuyển giá trị của một.

if (x < 4) { 
    // ran when x is 3, 2, 1, 0, -1, ... MIN_INT. 
} 

là logic tương đương với

if (x <= 3) { 
    // ran when x is 3, 2, 1, 0, -1, ... MIN_INT. 
} 

Tại sao trình biên dịch đã chọn một đại diện nội bộ trên một thường là một vấn đề tối ưu hóa, nhưng thực sự rất khó để biết nếu tối ưu hóa là động lực thật sự. Trong mọi trường hợp, các hàm tương đương chức năng như thế này là lý do tại sao ánh xạ lại không chính xác 100%. Có nhiều cách để viết một điều kiện có tác dụng tương tự trên cùng một đầu vào.

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