Bạn nói bạn đã quan tâm đến lý do tại sao, vì vậy:
Trong chế độ thực, một bộ phận là một "cửa sổ" 64K vào bộ nhớ vật lý và các cửa sổ này cách nhau 16 byte. Trong chế độ được bảo vệ, phân đoạn là cửa sổ cho bộ nhớ vật lý hoặc ảo, có kích thước và vị trí được xác định bởi hệ điều hành và có nhiều thuộc tính khác, bao gồm cấp độ đặc quyền mà quy trình phải truy cập.
Từ đây, mọi thứ tôi nói đều đề cập đến chế độ được bảo vệ.
Có một bảng trong bộ nhớ được gọi là bảng mô tả toàn cầu (GDT), là nơi thông tin về các kích thước cửa sổ và vị trí và các thuộc tính khác được lưu giữ. Cũng có thể có các bảng mô tả địa phương trên cơ sở từng quá trình và chúng hoạt động theo cách tương tự, vì vậy tôi sẽ chỉ tập trung vào GDT.
Giá trị bạn tải vào thanh ghi phân đoạn được gọi là bộ chọn phân đoạn phân đoạn. Nó là một chỉ mục trong GDT hoặc LDT, với một chút thông tin bảo mật bổ sung. Đương nhiên nếu một chương trình cố tải một bộ mô tả nằm ngoài giới hạn của GDT, một ngoại lệ sẽ xảy ra. Ngoài ra nếu quá trình này không có đủ đặc quyền để truy cập phân đoạn hoặc một thứ khác không hợp lệ, ngoại lệ sẽ xảy ra.
Khi ngoại lệ xảy ra, hạt nhân sẽ xử lý nó. Loại ngoại lệ này có thể sẽ được phân loại là lỗi phân đoạn. Vì vậy, hệ điều hành giết chết chương trình của bạn.
Có một cảnh báo cuối cùng: trong tập lệnh x86, bạn không thể tải giá trị ngay lập tức vào thanh ghi phân khúc. Bạn phải sử dụng thanh ghi trung gian hoặc toán hạng bộ nhớ hoặc POP vào thanh ghi phân khúc.
MOV DS, 160 ;INVALID - won't assemble
MOV AX, 160 ;VALID - assembles, but will probably result in an
MOV DS, AX ;exception, and thus the death of your program
Tôi nghĩ cần phải chỉ ra rằng kiến trúc cho phép đống phân đoạn. Nhưng AFAIK, khi nói đến các hệ điều hành chủ đạo x86, thanh ghi segment phục vụ chỉ có một vài mục đích:
- Cơ chế bảo mật, chẳng hạn như giữ các quy trình không gian người dùng từ làm hại lẫn nhau hoặc hệ điều hành
- Đối phó với nhiều/bộ vi xử lý đa lõi
- Bộ nhớ cục bộ: tối ưu hóa, một số hệ điều hành (bao gồm Linux và Windows) sử dụng thanh ghi phân đoạn cho lưu trữ cục bộ (TLS). Vì các chủ đề chia sẻ cùng một không gian địa chỉ, nên khó có thể biết một chuỗi nào là "biết" nơi mà vùng TLS của nó không sử dụng cuộc gọi hệ thống hoặc lãng phí một thanh ghi ... nhưng vì các thanh ghi phân đoạn thực sự vô dụng, không có hại trong "lãng phí" chúng vì lợi ích của TLS nhanh. Lưu ý rằng khi thiết lập điều này, một hệ điều hành có thể bỏ qua thanh ghi phân đoạn và ghi trực tiếp vào sổ đăng ký bộ mô tả, là các thanh ghi "ẩn" được sử dụng để lưu trữ tra cứu GDT/LDT được kích hoạt bởi tham chiếu đến thanh ghi phân đoạn, trong trường hợp này nếu bạn thử để đọc từ phân khúc đăng ký, bạn sẽ không nhìn thấy nó.
Ngoài phân đoạn trên mỗi luồng cho TLS, thực sự chỉ có một số phân đoạn (số lần bộ xử lý) được sử dụng và chỉ bởi hệ điều hành. Các chương trình ứng dụng có thể hoàn toàn bỏ qua thanh ghi phân đoạn.
Điều này là do thiết kế hệ điều hành, không phải bất kỳ giới hạn kỹ thuật nào. Có thể có các hệ điều hành nhúng yêu cầu các chương trình không gian người dùng để làm việc với các thanh ghi phân đoạn, mặc dù tôi không biết bất kỳ điều gì.
Lỗi là gì? – Blorgbeard
Theo một hệ điều hành, hoặc tự do? 16 chế độ bảo vệ thực hoặc 32 bit? Mã nào không biên dịch? Ví dụ tối thiểu 16 bit với các hiệu ứng quan sát được: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d4aae6183b98564819107b44a77641979c35d2c3/segment_registers.S –