2012-03-13 45 views
43

Tôi không phải là người mới khởi động và hệ thống SW, nhưng tôi không biết nguồn gốc của lý do tại sao chương trình chung bắt đầu tại 0x8000. Tôi đã biết địa chỉ 0x8000 đã được sử dụng làm địa chỉ bắt đầu trong chương trình C/C++ bình thường.Tại sao chương trình chung thường bắt đầu ở mức 0x8000?

Kích thước tối thiểu của bộ nạp khởi động cho chương trình chung có lên đến 0x8000 không? Hoặc là kích thước khối tối thiểu của ROM nên được phân bổ cho bộ nạp khởi động 32KB? Hoặc là có một lý do khác?

Tôi muốn biết điều này, về mặt lịch sử hoặc hợp lý và từ quan điểm địa chỉ ảo.


Tôi đánh giá cao tất cả, thời gian và trợ giúp của bạn về vấn đề này. Để đặt câu hỏi rõ ràng hơn, câu hỏi liên quan đến địa chỉ ảo không phải với vật lý.

Tôi về cơ bản đồng ý với ý kiến ​​của R từ quan điểm địa chỉ bộ nhớ vật lý.

Không nói một hệ thống cụ thể, ví dụ linux (ngay cả trong android), RTOS chung (hạt nhân, và những người khác, đặc biệt là phần liên kết ARM), tất cả đều sử dụng địa chỉ 0x8000 làm chương trình địa chỉ bắt đầu chung. được đặt tên như crt_begin.o, crt.o, v.v. tại 0x0 với bộ tải tồn tại trong khu vực này.

Vì vậy, tôi đoán kích thước tối thiểu của bộ nạp khởi động cho chương trình chung là 32KB xem xét kích thước khối nếu nó được đặt tại BootROM trong thời gian khởi động (khởi động nguội).

Ummm, Nhưng tôi không chắc chắn ...

+16

Bạn đang nói về hệ thống nào? –

+2

Tôi không có bất kỳ nguồn đáng tin cậy nào cho điều này, nhưng tôi có thể đưa ra một dự đoán đủ điều kiện. Trong lịch sử nhiều bộ vi xử lý, đặc biệt 8 bit, đã có tính năng gọi là [zero page] (http://en.wikipedia.org/wiki/Zero_page) có nghĩa là các ô nhớ tại địa chỉ 0x00 - 0xFF có hỗ trợ hướng dẫn tới thực thi nhanh hơn. Tôi tin rằng điều này đã được Motorola giới thiệu trở lại trong ngày, vì họ đã đăng ký bộ nhớ I/O đăng ký trên các MCU cũ như 6800. -> – Lundin

+2

Vì vậy, bạn sẽ muốn khu vực đầu tiên của bộ nhớ này được chiếm bởi các tế bào RAM hoặc đăng ký đặc biệt . Sau đó, ý nghĩa là phần không gian địa chỉ xuất hiện sau trang không có cùng tính chất: RAM và/hoặc thanh ghi. Điều này sẽ mất rất nhiều kb, có thể lên đến 0x6000 hoặc một số như vậy. Sau đó, tôi cho rằng thuận tiện khi đặt ROM (bộ nhớ chương trình) tại địa chỉ đồng đều và 0x8000 thuận tiện. Tôi khá chắc chắn rằng câu trả lời cho câu hỏi này có thể được tìm thấy trong các thiết kế bộ xử lý Motorola đầu tiên. – Lundin

Trả lời

19

Nói chung, trên tất cả các hệ thống nhúng nhỏ nhất, nền tảng ABI nhà thiết kế muốn tránh bao giờ có địa chỉ thấp nhất trong sử dụng để dereferences con trỏ null có thể bị mắc kẹt. Có một vài KB địa chỉ không hợp lệ cung cấp cho bạn một số an toàn bổ sung nếu con trỏ null bị bỏ qua với một mảng hoặc thành phần cấu trúc bù đắp, như trong null_ptr->some_member.

+3

Tôi không tin rằng đây là lý do, tôi đã làm việc với một số hệ thống nhúng nơi địa chỉ 0 là bộ nhớ hợp lệ và địa chỉ, trong khi cùng lúc NVM bắt đầu ở 8000. – Lundin

+5

... đặc biệt là địa chỉ 0x8000 tồn tại trước C ngôn ngữ và NULL con trỏ trở nên phổ biến. Có lẽ ngay cả trước khi C được phát minh? – Lundin

+0

Khi tôi hiểu nó, bạn không muốn các con trỏ "thực" là 0, bao giờ, ngay cả trên các hệ thống mà HW là ok với nó. Vì vậy, nếu 'malloc()' trả về 0, bạn biết nó thất bại. Vì vậy, trên các hệ thống mà địa chỉ 0 không bẫy, bộ nhớ thường được cấp phát cho các mục đích cụ thể như các trình xử lý ngắt. – MSalters

6

Tùy thuộc vào hệ thống và các chương trình bắt đầu tại các địa chỉ khác nhau trên các hệ thống khác nhau. Dưới Unix, thông thường (hoặc thậm chí có thể yêu cầu bởi Posix) để sử dụng địa chỉ 0 làm con trỏ rỗng và không ánh xạ trang đầu tiên của bộ nhớ ảo, để dereferencing một con trỏ rỗng sẽ dẫn đến vi phạm phân đoạn. Tôi nghi ngờ rằng các hệ thống khác sử dụng địa chỉ 0 làm con trỏ null hoạt động tương tự (nhưng số tiền dự trữ là có thể thay đổi). (Trong lịch sử, thường là bản đồ trang đầu tiên chỉ đọc , và điền nó bằng số không, làm điều đó một con trỏ rỗng sẽ hoạt động như thể nó là một chuỗi rỗng, một con trỏ đến "". Đó là khoảng 25 năm Tuy nhiên.)

tôi hy vọng rằng, ngay cả ngày hôm nay, một số hệ thống nhúng làm tải chương trình bắt đầu tại địa chỉ 0.

2

tôi nghi ngờ trong rất nhiều trường hợp, 32K đầu tiên được dành riêng cho các màn hình sử dụng mã/ram. Trong rất nhiều 8.051 đánh giá nó không phải là không phổ biến để mặc định 0x1000 hoặc 0x2000 cho tất cả các ứng dụng tùy thuộc vào màn hình cư trú (một số mà làm việc như debuggers quá).

32K có thể là bộ nạp trình khởi động u-boot/etc của bạn.

3

Đó là phần nào tùy ý và trên Linux, ít nhất được quyết định bởi trình liên kết. Ý tưởng chung là để dành một số không gian để bắt ngoại lệ con trỏ NULL. Để giúp ngăn chặn không gian hạt nhân NULL dereferences con trỏ từ thực hiện mã người dùng tùy ý trong chế độ hạt nhân, Linux ngăn cản bạn từ bản đồ rất dưới cùng của bộ nhớ. /proc/sys/vm/mmap_min_addr kiểm soát địa chỉ thấp nhất bạn có thể lập bản đồ (bạn có thể thay đổi địa chỉ thành 0 và ánh xạ một trang tại 0 nếu bạn muốn).

Trên linux, bạn có thể xem bản đồ bộ nhớ bằng cách xem trong /proc. Ví dụ,

genwitt ~> cat /proc/self/maps 
00400000-0040c000 r-xp 00000000 08:01 354804        /bin/cat 
0060b000-0060c000 r--p 0000b000 08:01 354804        /bin/cat 
0060c000-0060d000 rw-p 0000c000 08:01 354804        /bin/cat 
01dda000-01dfb000 rw-p 00000000 00:00 0         [heap] 
7f5b25913000-7f5b25a97000 r-xp 00000000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25a97000-7f5b25c97000 ---p 00184000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25c97000-7f5b25c9b000 r--p 00184000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25c9b000-7f5b25c9c000 rw-p 00188000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25c9c000-7f5b25ca1000 rw-p 00000000 00:00 0 
7f5b25ca1000-7f5b25cc2000 r-xp 00000000 08:01 436061      /lib64/ld-2.14.1.so 
7f5b25cd2000-7f5b25e97000 r--p 00000000 08:01 126248      /usr/lib64/locale/locale-archive 
7f5b25e97000-7f5b25e9a000 rw-p 00000000 00:00 0 
7f5b25ec0000-7f5b25ec1000 rw-p 00000000 00:00 0 
7f5b25ec1000-7f5b25ec2000 r--p 00020000 08:01 436061      /lib64/ld-2.14.1.so 
7f5b25ec2000-7f5b25ec3000 rw-p 00021000 08:01 436061      /lib64/ld-2.14.1.so 
7f5b25ec3000-7f5b25ec4000 rw-p 00000000 00:00 0 
7fff18c37000-7fff18c58000 rw-p 00000000 00:00 0       [stack] 
7fff18d0c000-7fff18d0d000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall]
2

Tôi tin rằng câu trả lời là có liên quan đến việc xử lý ngắt. Các địa chỉ xử lý ngắt được đặt trong phần cứng. Trong Intel 8086, có một bảng dịch trực tiếp trên mã trình xử lý ngắt và quy trình xử lý gián đoạn tương ứng. Có lẽ, điều này đã được thực hiện bởi một số mạch tổ hợp và do đó, để duy trì khả năng tương thích về phía trước, nó sẽ là hợp lý hơn để đặt chúng vào lúc bắt đầu của bộ nhớ hơn là ở cuối để ngăn chặn những thay đổi mọi lúc. Vì vậy, địa chỉ bắt đầu thực hiện sẽ nằm ở đầu kia của bộ nhớ. Ngoài ra, cần phải có đủ mã trong khối đó để tải chương trình phân đoạn bộ nhớ và lệnh nhảy để chuyển sang thực thi mã từ địa chỉ mã đó.

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