2010-05-20 30 views
6

Tôi có rất nhiều sự nhầm lẫn về sự khác biệt giữa con trỏ "xa" và con trỏ "khổng lồ", tìm kiếm nó trên google để tìm giải pháp, không thể tìm thấy. Có thể bất kỳ một trong những giải thích cho tôi sự khác biệt giữa hai. Ngoài ra, khái niệm chuẩn hóa chính xác liên quan đến con trỏ rất lớn là gì.Điều gì có nghĩa là bình thường hóa trong các con trỏ lớn

Hãy donot cho tôi sau đây hoặc bất kỳ câu trả lời tương tự:

"Sự khác biệt duy nhất giữa một con trỏ đến nay và một con trỏ khổng lồ là một con trỏ lớn được chuẩn hóa bởi trình biên dịch Một con trỏ bình thường là một trong đó. có càng nhiều địa chỉ càng tốt trong phân đoạn, có nghĩa là chênh lệch không bao giờ lớn hơn 15. Một con trỏ khổng lồ được chuẩn hóa chỉ khi số học con trỏ được thực hiện trên nó. Mức chênh lệch phải nhỏ hơn 16 vì phân đoạn có thể biểu thị bất kỳ giá trị nào lớn hơn hoặc bằng 16 (ví dụ: Địa chỉ tuyệt đối 0x17 ở dạng chuẩn hóa sẽ là 0001:0001. Trong khi một con trỏ xa có thể giải quyết địa chỉ tuyệt đối 0x17 với 0000:0017, đây không phải là một con trỏ rất lớn (được chuẩn hóa) vì bù đắp lớn hơn 0000F.). Con trỏ lớn cũng có thể được tăng lên và giảm đi bằng cách sử dụng toán tử số học, nhưng vì chúng được chuẩn hóa nên chúng sẽ không quấn như con trỏ xa. ”

Ở đây khái niệm chuẩn hóa không được giải thích rõ ràng, hoặc có thể là tôi không thể hiểu nó rất tốt.

bất cứ ai có thể cố gắng giải thích khái niệm này từ một quan điểm mới bắt đầu xem.

Cảm ơn, Rahamath

+0

Nền tảng này là gì? Một số loại mục tiêu được nhúng với không gian địa chỉ 16 bit? Có vẻ như các con trỏ xa/rất lớn thực sự có phân đoạn và độ lệch, trái ngược với các địa chỉ tuyến tính đơn giản. – tomlogic

+5

1985 được gọi là, muốn công nghệ lame của nó trở lại. – ergosys

+0

ergosys, bạn sẽ ngạc nhiên khi biết rằng vẫn còn có bộ điều khiển nhúng dựa trên kiến ​​trúc 80186 được sử dụng ngày nay, và trong khi chúng không còn được quảng cáo bởi intel và AMD, bạn vẫn có thể mua chúng. –

Trả lời

13

Ban đầu 8086 là phần mở rộng của bộ xử lý 8 bit 8085. 8085 chỉ có thể địa chỉ 65536 byte với bus địa chỉ 16 bit. Khi Intel phát triển 8086, họ muốn phần mềm tương thích càng tốt với bộ xử lý 8 bit cũ, vì vậy họ đã giới thiệu khái niệm về địa chỉ bộ nhớ phân đoạn. Điều này cho phép chạy phần mềm 8 bit để sống trong phạm vi địa chỉ lớn hơn mà không cần chú ý. 8086 có một bus địa chỉ 20 bit và do đó có thể xử lý tới 1 MB bộ nhớ (2^20). Đáng tiếc là nó không thể giải quyết trực tiếp bộ nhớ này, nó phải sử dụng thanh ghi phân đoạn để làm điều đó. Địa chỉ thực được tính toán bằng cách thêm giá trị phân đoạn 16 bit được dịch chuyển bằng 4 sang bên trái được thêm vào bù đắp 16 bit.

Example: 
Segment 0x1234 Offset 0x5678 will give the real address 
    0x 1234 
    +0x 5678 
    --------- 
    =0x 179B8 

Như bạn đã thấy, thao tác này không có tính từ, nghĩa là bạn có thể tạo địa chỉ thực với các kết hợp phân đoạn và bù khác.

0x 1264    0x 1111 
    +0x 5378    +0x 68A8 
    ---------    ---------  etc. 
    =0x 179B8    =0x 179B8 

Có trên thực tế 4096 kết hợp khác nhau càng tốt, bởi vì 3 Nibbles chồng chéo (3*4 = 12 bit, 2^12 = 4096). Kết hợp chuẩn hóa là chỉ có một trong 4096 giá trị có thể có 3 giá trị cao của bù đắp về 0. Trong ví dụ của chúng tôi nó sẽ là:

0x 179B 
    +0x 0008 
    --------- 
    =0x 179B8 

Sự khác biệt giữa một far và một con trỏ huge không nằm trong bình thường, bạn có thể có không bình thường huge con trỏ, nó absolutly phép. Sự khác biệt là trong mã được tạo ra khi thực hiện số học con trỏ. Với con trỏ xa khi tăng hoặc thêm giá trị cho con trỏ sẽ không có xử lý tràn và bạn sẽ chỉ có thể xử lý 64K bộ nhớ.

char far *p = (char far *)0x1000FFFF; 
p++; 
printf("p=%p\n"); 

sẽ in 1000:0000 Đối với con trỏ rất lớn trình biên dịch sẽ tạo ra mã cần thiết để xử lý các tiến hơn.

char huge *p = (char huge *)0x1000FFFF; 
p++; 
printf("p=%p\n"); 

sẽ in 2000:0000

này có nghĩa là bạn phải cẩn thận khi sử dụng xa hoặc con trỏ lớn như chi phí của số học với họ là khác nhau.

Người ta cũng không nên quên rằng hầu hết các trình biên dịch 16 bit có thư viện không xử lý các trường hợp này một cách chính xác đôi khi đưa ra phần mềm lỗi. Microsofts trình biên dịch chế độ thực không xử lý các con trỏ lớn trên tất cả các hàm chuỗi của nó. Borland thậm chí còn tồi tệ hơn ngay cả khi các chức năng ghi nhớ (memcpy, memset, v.v.) không xử lý tràn bù đắp. Đó là lý do tại sao nên sử dụng các con trỏ chuẩn hóa với các chức năng thư viện này, khả năng bù đắp bù đắp thấp hơn với chúng.

+0

Cảm ơn lời giải thích tuyệt vời này !! – wrapperm

10

điều đầu tiên phải hiểu là làm thế nào một con trỏ phân đoạn được chuyển đổi thành một tuyến tính địa chỉ nhà. Đối với ví dụ bạn có, chuyển đổi là:

linear = segment * 16 + offset; 

Do đó, có thể biểu thị cùng một địa chỉ tuyến tính bằng cách sử dụng các kết hợp phân đoạn/bù khác nhau. Ví dụ, phân khúc/kết hợp bù đắp sau tất cả tham khảo các địa chỉ tuyến tính giống nhau:

0004:0000 
0003:0010 
0002:0020 
0001:0030 
0000:0040 

Vấn đề ở đây là nếu bạn đã ptr1 với một địa chỉ phân đoạn của 0100:0000 và ptr2 với một địa chỉ phân đoạn của 0010:0020, một so sánh đơn giản sẽ xác định rằng ptr1 != ptr2 mặc dù chúng thực sự trỏ đến cùng một địa chỉ.

Chuẩn hóa là quá trình mà bạn chuyển đổi địa chỉ thành một biểu mẫu sao cho nếu hai con trỏ không chuẩn hóa tham chiếu đến cùng một địa chỉ tuyến tính, cả hai đều sẽ được chuyển đổi thành cùng một biểu mẫu chuẩn hóa.

+0

+1 để đề cập đến so sánh con trỏ, tôi quên rằng trong câu trả lời của mình. –

+0

Số sai, 0100: 0000 == 00FF: 0010 == 00FE: 0020, v.v. –

+0

@HansPassant - dang, vì lý do nào đó tôi đã sử dụng nhị phân cho phân khúc và hex trên chỉ mục. Sẽ sửa chữa điều đó .. –

1

Như tôi nhớ lại, đó là một cái gì đó như thế này:

  • gần con trỏ trỏ tới bộ nhớ trong phân khúc tương tự (con trỏ).
  • Con trỏ trỏ tới bộ nhớ trong phân khúc khác.
  • Con trỏ cực lớn cho phép bạn trỏ đến bộ nhớ lớn hơn phân đoạn (vì vậy bạn có thể có khối> 64k và thực hiện số học trên con trỏ của mình và những gì Samuel nói).

Nếu bạn là người mới bắt đầu, tốt nhất bạn nên quên rằng bạn đã nghe nói về Near/Far/Huge. Chúng chỉ có ý nghĩa trong mô hình bộ nhớ phân đoạn 16 bit thường thấy trên đầu Intel 80x86. Trong vùng đất 32 và 64 bit (nghĩa là mọi thứ từ năm 1994), bộ nhớ chỉ là một khối tiếp giáp lớn, do đó, một con trỏ chỉ là một con trỏ (như một ứng dụng đơn có liên quan).

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