Tôi không hiểu. Bất kỳ hướng dẫn nào cũng quá kỹ thuật. Bộ nhớ phẳng và phân đoạn là gì? Cách giải quyết bộ nhớ, cách sắp xếp byte trong bộ nhớ? Điều nào là tốt nhất cho các máy tính 32-bit? Ai có thể giải thích nó? Chế độ thực và chế độ được bảo vệ phải làm gì với bộ nhớ phẳng hoặc phân đoạn? Cảm ơn!Bộ nhớ phân đoạn và bộ nhớ phẳng
Trả lời
Nếu bạn chỉ quan tâm đến các ứng dụng đang chạy trên các hệ điều hành 32/64 bit hiện có, bạn có thể chỉ cần quên bộ nhớ được phân đoạn. Trên hệ điều hành 32 bit, bạn có thể giả định rằng bạn có 4 GB dung lượng bộ nhớ “phẳng”. Phẳng có nghĩa là bạn có thể thao tác địa chỉ với giá trị 32 bit và thanh ghi, như bạn mong đợi. Trên các bộ xử lý 16 bit, tôi tin rằng một địa chỉ rộng 20 bit và bạn không thể lưu trữ trong sổ đăng ký, vì vậy bạn phải lưu trữ cơ sở trong một thanh ghi và chỉ định địa chỉ thực, bạn phải thêm một bù đắp cho cơ sở đó. (Nếu tôi nhớ chính xác, cơ sở được nhân với 16, thì bù đắp được thêm vào để có địa chỉ thực.) Điều này có nghĩa là bạn chỉ có thể địa chỉ 64 KB cùng một lúc; bộ nhớ đã được "phân đoạn" trong khối 64 KB.
Thành thật mà nói, tôi nghĩ lý do duy nhất mà người mới bắt đầu vẫn nghe về điều đó là bởi vì rất nhiều sách hướng dẫn và sách cũ 16 bit vẫn còn xung quanh. Nó thực sự không cần thiết để hiểu làm thế nào một chương trình làm việc ở cấp độ lắp ráp. Bây giờ nếu bạn muốn học phát triển hệ điều hành, đó là một câu chuyện khác. Vì PC khởi động ở chế độ 16 bit, bạn sẽ cần phải học ít nhất là đủ để có thể kích hoạt chế độ 32 bit phẳng.
Chỉ cần nhận thấy bạn cũng đã hỏi về chế độ thực so với chế độ được bảo vệ. Chế độ thực là chế độ mà MS DOS sử dụng. Bất kỳ chương trình nào cũng có quyền truy cập vào bất kỳ tính năng phần cứng nào, ví dụ như thường trực tiếp nói chuyện với bộ điều khiển cạc đồ họa để in một thứ gì đó. Nó không gây ra bất kỳ vấn đề nào vì nó không phải là một hệ điều hành đa nhiệm.
Nhưng trên mọi hệ điều hành hiện đại, chương trình bình thường không truy cập phần cứng trực tiếp, chúng thậm chí không truy cập trực tiếp vào bộ nhớ. Hệ điều hành quản lý phần cứng và quyết định quá trình nào sẽ chạy trên (các) bộ xử lý. Nó cũng quản lý một không gian địa chỉ ảo cho mọi quá trình. Đây là loại tính năng có sẵn với chế độ bảo vệ, mà tôi tin rằng đi kèm với 386, đó là bộ xử lý 32 bit đầu tiên cho PC.
+1 để có câu trả lời chi tiết! –
Vì vậy, địa chỉ bộ nhớ phân đoạn giống như một công thức phù hợp với thanh ghi 16 bit và xác định địa chỉ từ bộ nhớ lớn hơn dung lượng đăng ký. PC khởi động ở chế độ địa chỉ 16 bit nghĩa là BIOS không thể đọc địa chỉ 32 bit? Cảm ơn! – ali
@ali: Tôi không biết BIOS được triển khai như thế nào.Về mặt kỹ thuật, tôi đoán rằng không có gì ngăn cản một BIOS chuyển đổi sang 32 bit và sau đó quay trở lại 16 bit nếu nó thực sự cần thiết vì một lý do nào đó. –
Hướng dẫn truy cập nội dung nào đó (bộ nhớ, I/O, bộ nhớ ánh xạ I/O, vv) đôi khi cung cấp địa chỉ đầy đủ (từ quan điểm của lớp thực thi bộ xử lý), đôi khi chúng cung cấp bù đắp. Các bước nhảy gần hoặc tương đối của bạn ví dụ bộ đếm chương trình là địa chỉ cơ sở và lệnh cung cấp một bù đắp cho cơ số đó, thêm hai số này lại với nhau và bạn nhận được địa chỉ (ở cấp đó).
Thực hiện hệ thống 16 bit nơi bạn có thanh ghi 16 bit và giới hạn không gian địa chỉ tối đa 64KByte. Một cách rất đơn giản để mở rộng bộ nhớ đó là phân đoạn. Thay vì thanh ghi có chứa toàn bộ địa chỉ, thanh ghi trong hướng dẫn của bạn có chứa một phần bù đắp cho một cơ sở, giống như một lệnh liên quan đến máy tính. Ngoại trừ trong trường hợp này có một thanh ghi khác được sử dụng làm địa chỉ cơ sở. Bạn thấy điều này trong một số kiến trúc mà muốn dễ dàng mở rộng phạm vi địa chỉ của họ mà không quá nhiều nếu có bất kỳ sửa đổi nào đối với lõi. (có thể được thực hiện trong bộ điều khiển bộ nhớ mà không sửa đổi lõi) Trong trường hợp của x86 có một vài thanh ghi. Một đã được sử dụng để mở rộng phạm vi thực hiện, chi nhánh. Một cách khác để mở rộng phạm vi tiếp cận dữ liệu, tải và lưu trữ. Địa chỉ của một chi nhánh không liên quan đến máy tính được tính toán bằng cách sử dụng đoạn mã chuyển 4 bit còn lại sau đó được thêm vào thanh ghi được chỉ định trong lệnh. Đối với các tải và cửa hàng không liên quan đến máy tính, thanh ghi phân đoạn dữ liệu đã được sử dụng, hãy dịch sang trái 4 thêm thanh ghi được chỉ định trong lệnh. vì vậy nếu bạn muốn địa chỉ 0x123456789 bạn có thể có đăng ký phân khúc chứa 0x12340000 và thanh ghi được sử dụng để xử lý chứa 0x56789 hoặc phân đoạn 0x12345678 và gpr chứa 0x9. Pc tương đối địa chỉ là tất nhiên phân khúc + pc + bù đắp.
Điều này dẫn đến việc áp dụng các kiểu bộ nhớ khác nhau. nhỏ bé, nhỏ, trung bình, lớn, lớn. Bạn có thể tưởng tượng rằng mô hình nhỏ nhất sẽ có quy tắc hoặc giả định trong trường hợp x86 rằng mọi thứ nằm trong không gian bộ nhớ 64K, trình biên dịch và mã của bạn không bao giờ phải lo lắng về các thanh ghi phân đoạn, chúng được giả định là cố định. Đối với các mô hình lớn hơn hoặc khi sử dụng một con trỏ xa đến xa hơn thì không có vấn đề gì lớn, bạn thiết lập phân đoạn dữ liệu sau đó thiết lập bù đắp dữ liệu và thực hiện tải hoặc lưu trữ. Đối với mã, bạn có thể tưởng tượng nó một chút khó khăn hơn, kể từ khi bạn thay đổi đoạn mã đăng ký nó ảnh hưởng đến địa chỉ tổng thể mà bạn đang tìm nạp hướng dẫn. Bạn có thể muốn một giải pháp phần cứng để cho phép một chi nhánh sửa đổi cả phân khúc và bù đắp, hoặc bạn có thể làm điều đó trong mã (nếu phần cứng được cho phép). Tôi sẽ không nhầm lẫn bạn với cái đó ngay bây giờ.
Bất cứ khi nào bạn có một mảng trong mã:
unsigned char abc[123];
Đó là về cơ bản giống nhau. Địa chỉ cơ sở, địa chỉ nơi mảng bắt đầu trong bộ nhớ giống như phân khúc của bạn và chỉ mục là phần bù của bạn. Nếu trong abc ở trên tại địa chỉ 0x1004 thì abc [5] ở địa chỉ 0x1004 + 5 = 0x1009. Không chuyển dịch như phân đoạn x86: địa chỉ offset, nhưng cùng khái niệm thêm cơ sở và bù đắp. Một số kiến trúc phân đoạn bạn không có bổ sung, một số bit trong một số đăng ký ở đâu đó là các bit trên. Lấy địa chỉ 0x12345 trên một trong các hệ thống này 0x1 phải nằm trong phân đoạn và 0x2345 trong gpr 16 bit. Bạn có thể nghĩ về nó như một sự thay đổi và thêm nếu bạn muốn, nhưng không giống như phân đoạn x86: bù đắp bạn cũng có thể nghĩ về nó như là một sự thay đổi và hoặc.
Không gian bộ nhớ phẳng là một chút ảo tưởng, đặc biệt là trong các hệ thống x86. x86 máy tính, 32 bit và thậm chí nhiều 64 bit, giới hạn số lượng không gian bộ nhớ phẳng để cắm thẻ vào tổng số 1Gig, tạo nhiều ý nghĩa cho hệ thống 32 bit, nơi bạn có tổng cộng 4 gig address space và là lý do tại sao một số trong số này cung cấp cho bạn một giới hạn 3 gig, hoặc cung cấp cho bạn những ảo ảnh của 4 gig, nhưng đã cắt nhỏ ra một số trong đó cho cắm trong thẻ. (nhiều mục trên bo mạch chủ của bạn nằm trong không gian này cũng như các plug thực tế trong thẻ). Tùy thuộc vào card màn hình và độ phân giải, vv đôi khi bạn không thể phù hợp với toàn bộ bộ đệm khung trong tập con của không gian ngoại vi đó, vì vậy bạn phải phân đoạn truy cập của bạn. bios có thể đã cho bạn địa chỉ 0x80000000 làm cơ sở trong không gian địa chỉ x86, sau đó trong một số đăng ký khác trong thẻ video bạn chỉ định địa chỉ trong không gian địa chỉ của thẻ video. cho mục đích trình diễn cho phép nói rằng bạn đã được cung cấp một cửa sổ 16MByte tại địa chỉ x86 0x80000000. 16Mbyte là 0x01000000. nếu bạn muốn truy cập địa chỉ 0x04321888 trong bộ nhớ video, bạn có thể tưởng tượng phải đặt đăng ký phân đoạn trong thẻ video thành 0x04, sau đó trong không gian địa chỉ x86 (cũng là không gian địa chỉ pci (e)) sử dụng địa chỉ 0x80321888.
Điểm mấu chốt ở đây là lấy một số bit từ đây và một số bit từ đó, đặt chúng lại với nhau và đó là địa chỉ tại đích. Khi giao dịch với các thiết bị ngoại vi có thể là một card video hoặc các bộ điều khiển I/O trên bo mạch, hoặc bộ điều khiển pci hoặc pcie, bạn phải học cách suy nghĩ về không gian địa chỉ đích. bộ xử lý có một không gian địa chỉ từ phối cảnh chương trình của bạn. Các mmu có thể và không tranh giành rằng vào một không gian địa chỉ vật lý, sau đó bạn có không gian địa chỉ pcie của bạn, và sau đó thiết bị ngoại vi truy cập thông qua pcie có không gian địa chỉ riêng của họ. Những gì intel và intel dựa trên pc thế giới đã làm cho bộ vi xử lý địa chỉ vật lý không gian và không gian địa chỉ pcie giống nhau. Ảo vs vật lý xáo trộn trong mmu vẫn còn đó, và cửa sổ vào không gian địa chỉ thiết bị ngoại vi vẫn còn đó, bạn vẫn cần phải lấy một chút địa chỉ từ đây và một chút từ đó để có được địa chỉ cuối cùng ở bất kỳ mục tiêu nào.
Thực và được bảo vệ phải thực hiện với quyền truy cập. Trong C ví dụ, bạn có thể tạo con trỏ, thay đổi con trỏ và tạo bất kỳ địa chỉ nào bạn muốn, không ngụ ý rằng bạn có thể poke xung quanh trong bộ nhớ ứng dụng khác, hoặc bộ nhớ của hạt nhân?Lý tưởng nhất là bạn không muốn để điều đó xảy ra như vậy cho mỗi ứng dụng khi bạn đang thực hiện các hướng dẫn cho ứng dụng đó bạn đang ở trong một máy ảo, mọi truy cập bộ nhớ là mã hoặc hướng dẫn đi qua bộ lọc nếu bạn muốn. Bộ lọc đó kiểm tra xem liệu truy cập đó có nằm trong không gian cho phép của chương trình hay không, nếu nó đi ra ngoài không gian ngoại lệ (suy nghĩ ngắt) ngoại lệ cho phép hạt nhân (không có các hạn chế này hoặc có các hạn chế khác nhau) để quyết định cho phép truy cập đó hoặc có thể ảo hóa quyền truy cập vào nội dung nào đó hoặc ném cảnh báo cho người dùng (Lỗi bảo vệ chung). Lấy ví dụ một chương trình máy ảo thực tế như vmware, cho phép chương trình ảo hóa thực sự chạy các hướng dẫn trên bộ xử lý, khi chương trình ảo truy cập những gì nó nghĩ là địa chỉ của card màn hình, lỗi bảo vệ xảy ra, driver vmware/applicaiton (nghĩ mức hạt nhân) lấy địa chỉ đó và giả mạo đáp ứng của thẻ video và trả về điều khiển cho ứng dụng. Để các lệnh thực hiện trên kim loại cho phép ảo hóa nhanh hơn nhiều để thay thế, đó là mô phỏng mọi lệnh xử lý. Đó là trường hợp cực đoan, ngay cả trình duyệt web bạn đang đọc này đã được ảo hóa để nó nghĩ rằng nó có một không gian bộ nhớ dựa trên một số địa chỉ cơ sở như 0x000 hoặc 0x8000, bạn biên dịch từng chương trình cho một hệ điều hành cụ thể không gian bộ nhớ ảo phẳng và hệ điều hành sẽ chăm sóc thay đổi địa chỉ từ ảo thành vật lý. Các trình duyệt web của bạn truy cập vào địa chỉ 0x8000 có thể là 0x12345678 vật lý và các chương trình máy nghe nhạc mp3 của bạn truy cập 0x8000 có thể là 0x2345678 vật lý nhưng với cả hai ứng dụng hướng dẫn của chúng là tính toán 0x8000.
Hỏi điều tốt nhất luôn là thuật ngữ tương đối, một trong những người tốt nhất là một người tồi tệ nhất. Bạn phải xác định tốt nhất từ tồi tệ nhất cho chính mình. Momentum và dư luận đã đưa x86 vào không gian bộ nhớ bằng phẳng hoặc ít nhất là ảo tưởng về không gian bộ nhớ phẳng từ góc độ lập trình viên, do đó bạn sẽ gặp ít rắc rối hơn với luồng.
Tôi khuyên bạn nên có một bản sao của 8086/8088 lập trình viên và hướng dẫn tham khảo phần cứng, người ta có thể có cho một vài Bucks.
Hãy mô phỏng như pcemu (Tôi có một bản sao cho mục đích này http://github.com/dwelch67/pcemu_samples) và chơi với các tập lệnh, trường cũ kỹ trước khi ảo hóa, bảo vệ vv Quay lại khi bạn đã phân đoạn và offsets tính như đã đề cập ở trên, dịch chuyển phân đoạn còn lại bốn và thêm bù đắp (tất cả được mô tả trong sách hướng dẫn này). Mỗi thế hệ kể từ khi đã làm một cái gì đó để cố gắng cải thiện khi cố gắng đảo ngược tương thích. Mà đã giúp lợi nhuận của khóa học nhưng biến các bộ xử lý thành những con thú khó chịu. Bạn nên quên đi các chi tiết x86 và tìm hiểu một số hệ thống sạch hơn, vì cách x86 đã phát triển, bạn sẽ có các lợi ích tối thiểu ví dụ cố gắng viết một cái gì đó trong asm trên mã được biên dịch. Do bộ vi xử lý từ các gia đình khác nhau thực thi cùng một mã ở các tốc độ khác nhau, thường thế hệ mới thực hiện mã điều chỉnh bằng tay từ trước với tốc độ chậm hơn nhiều. Bạn không thể điều chỉnh một thứ gì đó nhanh chóng trên tất cả các nền tảng, không phải nhanh hơn trình biên dịch có thể vì vậy chỉ cần để lại mã asm x86 cho các trình biên dịch. Làm việc trên nền tảng sane nơi bạn không có những vấn đề này và có thể điều chỉnh nếu bạn thích hoặc thực hiện một trình biên dịch tốt hơn, v.v.
Bộ nhớ phân đoạn là (trong 32 bit và 64 bit) lưu giữ từ một thời điểm khi yêu cầu bộ nhớ vượt quá kích thước của bus địa chỉ. Những cân nhắc như vậy là quá khứ và mọi người đều sử dụng mô hình phẳng bây giờ. Các nhà thiết kế của Motorola 68K (một bộ vi xử lý cao cấp hơn (với một bộ hướng dẫn thanh lịch hơn nhiều) cho 286 và nó là người tiền nhiệm) biết điều này và không bận tâm với phân đoạn địa chỉ. Nhưng lịch sử không quan tâm đến thẩm mỹ và Intel thắng và bây giờ tất cả chúng ta đều sử dụng hậu duệ của 386. –