Mengapa instruksi BIOS pertama terletak di 0xFFFFFFF0 ("top" RAM)?

51

Saya tahu bahwa BIOS memuat instruksi pertamanya dari 0xFFFFFFF0, tapi mengapa ini alamat khusus? Saya punya banyak pertanyaan dan berharap Anda dapat membantu saya dengan beberapa dari mereka, setidaknya.

Pertanyaan saya:

  • Mengapa instruksi BIOS pertama terletak di "atas" RAM 4 GB?
  • Apa yang akan terjadi jika komputer saya hanya memiliki 1 GB RAM?
  • Bagaimana dengan sistem dengan RAM lebih dari 4 GB (misalnya, 8 GB, 16 GB, dll.)?
  • Mengapa tumpukan diinisialisasi dengan beberapa nilai (dalam hal ini, nilai yang terletak di 0xFFFFFFF0)?

Saya sudah membaca tentang itu sore ini, dan saya masih belum mengerti.

Fernando Paladini
sumber
28
Tolong, satu pertanyaan untuk setiap pertanyaan.
Lightness Races with Monica
4
Saya suka bagaimana jawaban yang diterima bahkan tidak menyebutkan memori tersegmentasi atau mode pengalamatan sama sekali, dan satu-satunya tempat garis A20 bahkan disentuh adalah di komentar.
Imallett
Atmel AVR memulai eksekusi dari alamat 0, sedangkan Freescale HCS08 mulai dari 0xFFFE, iirc. Setiap keluarga prosesor memiliki karakteristiknya sendiri.
Nick T
2
@ imallett Saya suka bagaimana Anda memutuskan untuk mengeluh tentang hal itu di sini daripada meminta poster untuk memperbarui jawaban mereka dengan informasi lebih lanjut. Saya juga suka bagaimana Anda berpikir bahwa pengetahuan yang OP dapat temukan meskipun tujuan mengajukan pertanyaan adalah untuk mendapatkan pengetahuan tentang hal-hal yang mungkin sekarang sepenuhnya dipahami orang.
MonkeyZeus
2
@MonkeyZeus hingga saat ini, 9 komentator lain telah melakukan itu, dan itu masih belum berubah. Komentar saya, meskipun sarkastik, tidak kosong; ini adalah peringatan bagi netizen di masa depan, dan juga bagi OP.
imallett

Jawaban:

57

0xFFFFFFF0adalah saat CPU yang kompatibel dengan x86 mulai menjalankan instruksi saat dihidupkan. Itu merupakan aspek CPU yang dirancang khusus, tidak dapat diubah (tanpa perangkat keras tambahan) dan berbagai jenis CPU berperilaku berbeda.

Mengapa instruksi BIOS pertama terletak di "atas" dari RAM 4 GB?

Itu terletak di "atas" ruang alamat 4 GB - dan pada power-on BIOS atau UEFI ROM diatur untuk menanggapi pembacaan alamat tersebut.

Teori saya tentang mengapa ini adalah:

Hampir semua hal dalam pemrograman bekerja lebih baik dengan alamat yang berdekatan. Perancang CPU tidak tahu apa yang ingin dilakukan oleh seorang pembuat sistem dengan CPU, jadi itu adalah ide yang buruk bagi CPU untuk meminta alamat yang tepat di tengah-tengah ruang yang diperlukan untuk berbagai keperluan. Lebih baik untuk menjaga "keluar dari jalan" di bagian atas atau bawah ruang alamat. Tentu saja, ingatlah bahwa keputusan ini dibuat ketika 8086 baru, yang tidak memiliki MMU .

Di 8086, vektor interupsi ada di lokasi memori 0 ke atas. Vektor interupsi harus berada pada alamat yang diketahui dan diinginkan berada dalam RAM untuk fleksibilitas - namun tidak mungkin bagi perancang CPU untuk mengetahui berapa banyak RAM yang akan berada dalam suatu sistem. Jadi mulai dari 0 dan bekerja masuk akal bagi mereka (karena tidak ada sistem pada tahun 1978 ketika 8086 ditemukan akan memiliki 4 Gbytes RAM - jadi mengharapkan RAM berada di 0xFFFFFFF0 bukan ide yang baik), dan kemudian ROM harus menjadi di batas atas.

Tentu saja, dimulai dengan setidaknya 80286, vektor interupsi dapat dipindahkan ke lokasi awal yang berbeda selain 0, tetapi CPU x86 64-bit modern masih dapat boot dalam mode 8086, jadi semuanya masih bekerja dengan cara lama untuk kompatibilitas (seperti konyol seperti yang terdengar pada tahun 2015 masih membutuhkan CPU x86 Anda untuk dapat menjalankan DOS).

Jadi sejak vektor interupsi mulai dari 0 dan bekerja ke atas, ROM harus dimulai dari atas dan bekerja ke bawah.

Apa yang akan terjadi jika komputer saya hanya memiliki 1 GB RAM?

CPU 32-bit memiliki 4.294.967.296 alamat, bernomor 0 (0x00000000) hingga 4294967295 (0xFFFFFFFF). ROM dapat hidup di beberapa alamat dan RAM dapat hidup di tempat lain. Dengan MMU CPU, ini bahkan dapat diaktifkan dengan cepat. RAM tidak harus hidup di semua alamat.

Dengan hanya 1 GB RAM, beberapa alamat tidak akan merespons apa pun ketika dibaca atau ditulis. Ini dapat menyebabkan data yang tidak valid dibaca ketika alamat tersebut diakses atau penguncian sistem.

Bagaimana dengan sistem dengan RAM lebih dari 4 GB (mis: 8 GB, 16 GB, dll.)?

Menjaga agar tetap sederhana: CPU 64-bit memiliki lebih banyak alamat (yang merupakan salah satu hal yang membuatnya menjadi 64-bit - misalnya 0x000000000000000000 melalui 0xFFFFFFFFFFFFFFFF) misalnya, sehingga RAM tambahan "pas". Dengan asumsi CPU dalam mode panjang . Sampai saat itu RAM ada di sana, tidak bisa dialamatkan.

Mengapa tumpukan diinisialisasi dengan beberapa nilai (dalam hal ini, nilai yang terletak di 0xFFFFFFF0)?

Saya tidak dapat segera menemukan apa pun yang diberikan x86 pada penunjuk stack saat power-on, tetapi akhirnya harus dipindahkan oleh rutin inisialisasi juga begitu rutin itu mengetahui berapa banyak RAM dalam sistem. (@Eric Towers dalam komentar di bawah melaporkan bahwa ini disetel ke nol saat dihidupkan.)

LawrenceC
sumber
7
Yang terbaik untuk memikirkan ruang alamat sebagai ruang besar di mana hal-hal dapat ditetapkan oleh perangkat keras. Ketika CPU membaca / menulis memori, itu benar-benar melakukan komunikasi melalui bus, dan perangkat keras dapat memastikan hal-hal seperti RAM atau ROM merespons pada kisaran alamat tertentu. Jadi perangkat keras seperti itu harus memastikan ROM merespons pada 0xFFFFFFF0 ketika CPU diatur ulang. Tidak ada kewajiban yang melekat bahwa ROM muncul tepat setelah RAM. Itu dapat muncul di mana pun perangkat keras mengatakannya, tergantung pada kemampuan perangkat keras tersebut.
LawrenceC
4
Dimungkinkan untuk memiliki "lubang" atau ruang yang tidak ditetapkan yang tidak digunakan oleh ROM, RAM, atau apa pun - biasanya mengaksesnya akan menyebabkan penguncian sistem.
LawrenceC
16
Jawaban ini mengasumsikan bahwa CPU dapat menggunakan 32 bit alamat saat dalam mode 16 bit. Tetapi dalam mode 16 bit hanya bisa menggunakan 20 bit alamat. Alamat 0xFFFFFFF0ini tidak dapat dijangkau sampai setelah CPU beralih ke mode 32 bit. Terakhir kali saya memperhatikan kode BIOS, titik masuknya adalah 0xFFFF0.
kasperd
6
@ MichaelKjörling perhitungan Anda salah. Segmen bergeser dan offset bukan ORed, mereka ditambahkan. Jadi FFFF logis: FFF0 adalah fisik (1) 0FFE0 (di mana terkemuka 1 hadir jika A20 diaktifkan).
Ruslan
9
@kasperd Ada retasan di tempat - manajer memori memiliki 12 bit tinggi yang diatur ke 1 hingga lompatan panjang pertama terjadi. Jadi ya, secara logis, Anda bekerja dengannya 0xFFFF0, tetapi pada kenyataannya, itu dipetakan ke 0xFFFFFFF0. Saya berharap ini dilakukan untuk kompatibilitas dengan 8086 - baik itu dan lebih banyak CPU modern tampaknya menggunakan 0xFFFF0, tetapi CPU 32-bit sebenarnya mengakses 0xFFFFFFF0(dipetakan ke BIOS ROM).
Luaan
26

Itu tidak terletak di bagian atas RAM; terletak di ROM yang alamatnya ada di bagian atas ruang alamat memori, bersama dengan memori apa pun pada kartu ekspansi, seperti pengontrol Ethernet. Itu ada sehingga tidak akan konflik dengan RAM, setidaknya sampai Anda memiliki 4 GB diinstal. Sistem yang memiliki RAM 4 GB atau lebih dapat melakukan dua hal untuk menyelesaikan konflik. Motherboard murah mengabaikan bagian RAM yang bertentangan dengan tempat ROM berada. Yang layak memetakan ulang bahwa RAM tampaknya memiliki alamat di atas tanda 4 GB.

Saya tidak yakin apa yang Anda tanyakan tentang stack. Sudah pasti tidak diinisialisasi ke dalam ROM. Ketika CPU diatur ulang, ini awalnya dalam "mode nyata", di mana ia bertindak seperti 8086 yang asli dan menggunakan pengalamatan tersegmentasi 16-bit, yang memungkinkannya hanya untuk mengakses 1 MB memori. Kode BIOS terletak di atas 1 MB itu. BIOS mengambil tempat di RAM untuk mengatur tumpukan dan memuat dan menjalankan sektor pertama dari drive yang dapat di-boot pertama. Terserah OS untuk beralih ke mode 32 atau 64-bit setelah mengambil alih dan mengatur tumpukannya sendiri (satu per tugas / utas).

psusi
sumber
1
Terima kasih banyak atas jawabannya, tetapi @LawrenceC memberikan rincian lebih lanjut tentang jawabannya dan membantu saya tentang bagaimana semuanya bekerja. Bagaimanapun, terima kasih! Saya memberi Anda suara positif: 3
Fernando Paladini
13

Pertama, ini tidak ada hubungannya dengan RAM, sungguh. Kita berbicara tentang ruang alamat di sini - bahkan jika Anda hanya memiliki 16 MiB memori, Anda masih memiliki ruang alamat 32 bit penuh pada CPU 32-bit.

Ini sudah menjawab pertanyaan pertama Anda, sungguh - pada saat ini dirancang, PC dunia nyata tidak punya tempat di dekat memori 4 GiB penuh; mereka lebih banyak di kisaran memori 1-16 MiB. Ruang alamat, untuk semua maksud dan tujuan, gratis.

Sekarang, mengapa 0xFFFFFFF0 tepatnya? CPU tidak tahu berapa banyak BIOS yang ada. Beberapa BIOS mungkin hanya mengambil beberapa kilobyte, sementara yang lain mungkin mengambil megabita penuh memori - dan saya bahkan tidak masuk ke berbagai RAM opsional. CPU harus tertanam pada beberapa alamat untuk memulai - tidak ada yang bisa mengkonfigurasi CPU. Tapi ini hanya pemetaan ruang alamat - alamat dipetakan langsung ke dalam chip ROM BIOS (ya, ini berarti Anda tidak mendapatkan akses ke RAM 4 GiB penuh pada saat ini jika Anda memiliki banyak - tetapi itu bukan sesuatu yang istimewa, banyak perangkat memerlukan jangkauannya sendiri dalam ruang alamat). Pada CPU 32-bit, alamat ini memberi Anda 16 byte penuh untuk melakukan inisialisasi yang sangat mendasar - yang cukup untuk mengatur segmen Anda dan, jika perlu, mode alamat (ingat,boot nyata "prosedur". Pada titik ini, Anda tidak menggunakan RAM sama sekali - itu semua hanya ROM yang dipetakan. Faktanya, RAM bahkan belum siap untuk digunakan pada saat ini - itulah salah satu tugas BIOS POST! Sekarang, Anda mungkin berpikir - bagaimana mode nyata 16-bit mengakses alamat 0xFFFFFFF0? Tentu, ada segmen, jadi Anda memiliki ruang alamat 20-bit, tapi itu masih belum cukup baik. Nah, ada trik untuk itu - 12 bit tinggi dari alamat ditetapkan sampai Anda melakukan lompatan panjang pertama Anda, memberi Anda akses ke ruang alamat tinggi (sambil menolak akses ke sesuatu yang lebih rendah dari 0xFFF00000 - sampai Anda melakukan lompatan panjang) .

Semua ini adalah hal-hal yang sebagian besar disembunyikan dari programmer (belum lagi pengguna) pada sistem operasi modern. Anda biasanya tidak memiliki akses ke tingkat yang sangat rendah - beberapa hal sudah di luar penyelamatan (Anda tidak dapat beralih mode CPU mau tidak mau), beberapa secara eksklusif ditangani oleh kernel OS.

Jadi pandangan yang lebih baik datang dari pengkodean old-school pada MS DOS. Contoh khas lain dari memori perangkat yang dipetakan langsung ke ruang alamat adalah akses langsung ke memori video. Misalnya, jika Anda ingin menulis teks ke tampilan dengan cepat, Anda menulis langsung ke alamat B800:0000(plus offset - dalam mode teks 80x25, ini berarti (y * 80 + x) * 2jika ingatan saya tepat - dua byte per karakter, baris demi baris). Jika Anda ingin menggambar piksel demi piksel, Anda menggunakan mode grafik dan alamat awal A000:0000(biasanya, 320x200 pada 8 bit per piksel). Melakukan sesuatu yang berkinerja tinggi biasanya berarti menyelam ke dalam manual perangkat, untuk mengetahui cara mengaksesnya secara langsung.

Ini bertahan sampai hari ini - hanya disembunyikan. Pada Windows, Anda dapat melihat alamat memori yang dipetakan ke perangkat di Device manager - cukup buka properti seperti kartu jaringan Anda, buka tab Resources - semua item Memory Range adalah pemetaan dari memori perangkat ke ruang alamat utama Anda. Dan pada 32-bit, Anda akan melihat bahwa sebagian besar perangkat tersebut dipetakan di atas tanda 2 GiB (kemudian 3 GiB) - sekali lagi, untuk meminimalkan konflik dengan memori yang dapat digunakan pengguna, meskipun ini sebenarnya bukan masalah dengan memori virtual ( aplikasi tidak sampai mendekati ruang alamat perangkat keras yang sebenarnya - mereka memiliki sebagian besar memori tervirtualisasi, yang mungkin dipetakan ke RAM, ROM, perangkat atau file halaman, misalnya).

Adapun stack, well, itu akan membantu untuk memahami bahwa secara default, stack tumbuh dari atas. Jadi jika Anda melakukan push, penunjuk tumpukan baru akan berada di 0xFFFFFEC- dengan kata lain, Anda tidak mencoba untuk menulis ke alamat BIOS init :) Yang tentu saja berarti bahwa rutinitas BIOS init dapat menggunakan tumpukan dengan aman, sebelum memetakannya kembali suatu tempat yang lebih berguna. Dalam pemrograman old-school, sebelum paging menjadi default de facto, stack biasanya dimulai pada akhir RAM, dan "stack overflow" terjadi ketika Anda mulai menimpa memori aplikasi Anda. Perlindungan memori mengubah banyak hal ini, tetapi secara umum, itu mempertahankan kompatibilitas mundur sebanyak mungkin - perhatikan bagaimana bahkan CPU x86-64 yang paling modern masih dapat mem-boot MS DOS 5 - atau bagaimana Windows masih dapat menjalankan banyak aplikasi DOS yang tidak memiliki ide tentang paging.

Luaan
sumber
3
Jawaban luar biasa, hanya untuk memperluas dan mengatakan bahwa prosesor modern mulai menjatuhkan retasan seperti masking garis A20 , sehingga dukungan untuk kasus tepi yang lebih tua sedang sekarat.
Dasar
2
Ke paragraf terakhir: BIOS tidak dapat menggunakan stack "bebas": ia tidak dapat menulis ke ROM (yang 0xFFFFFFECakan dipetakan). Ini berarti tidak hanya tidak pushtetapi juga misalnya tidak call. Ini harus menunggu sampai RAM siap.
The Vee
7

Selain poin-poin lain yang disebutkan, mungkin bermanfaat untuk memahami apa alamat itu . Sementara arsitektur yang lebih baru mempersulit hal-hal, secara historis sebuah mesin akan pada setiap siklus memori menampilkan alamat yang diinginkan pada 20 hingga 32 kabel (tergantung pada arsitektur, dengan beberapa trik khusus untuk mencatat apakah perlu sepasang atau berempat byte secara bersamaan); berbagai bagian dari sistem memori akan memeriksa keadaan kabel-kabel itu dan mengaktifkan diri ketika mereka melihat kombinasi tertentu dari nilai tinggi dan rendah.

Jika sebuah mesin dengan 32 kabel alamat hanya perlu menggunakan 1MB RAM dan 64KB ROM [cukup masuk akal untuk beberapa pengendali yang disematkan] itu mungkin mengaktifkan RAM untuk semua alamat di mana kabel alamat atas rendah dan ROM untuk semua alamat di mana ia berada. tinggi. Kawat alamat bawah 20 kemudian akan diikat ke RAM untuk memilih salah satu dari 1.048.576 byte dan 16 terbawah akan ditransfer ke ROM juga, untuk memilih salah satu dari 65.536 byte. 11 kabel alamat yang tersisa tidak akan terhubung dengan apa pun.

Pada mesin seperti itu, akses ke alamat 0x00100000-0x001FFFFF akan sama dengan akses ke alamat RAM 0x00000000-0x000FFFFF. Demikian juga dengan alamat 0x000200000-0x0002FFFFF, atau 0x7FF00000-0x7FFFFFFFF. Alamat di atas 0x80000000 akan membaca ROM, dengan pola 64K berulang di seluruh ruang.

Meskipun prosesor memiliki ruang alamat 4.294.967.296 byte, tidak perlu ada perangkat keras yang mengenali banyak alamat berbeda. Menempatkan vektor reset di dekat bagian atas ruang alamat adalah desain yang akan bekerja dengan baik terlepas dari seberapa banyak atau sedikit RAM dan ROM yang dimiliki sistem dan menghindari kebutuhan untuk sepenuhnya memecahkan kode ruang alamat.

supercat
sumber
Poin bagus - Anda tidak akan menemukan perangkat keras 64-bit yang akan mendukung apa pun yang dekat dengan ruang memori 64-bit yang dapat dialamatkan (atau bahkan 1x10 ^ -12 darinya).
Dasar
3

Teory saya adalah karena kami menggunakan logika negatif, yang digital (1) tidak ada tegangan sama sekali (O volts) Kami hanya perlu meletakkan ketegangan pada 4 bit terakhir pada inisialisasi sehingga penghitung program (atau penunjuk Instruksi) lacates di 1111 1111 1111 1111 1111 1111 1111 0000. Kami tidak harus mengatasi 28 bit atas karena kebanyakan cpu (lama)) adalah 16 bit dan camilan yang lebih rendah dapat ditangani oleh satu chip alamat di masa lalu. Sekarang karena kita memiliki 64 bit dengan kompatibilitas ke 32 bit dan 32 bit ke 16 bit, couild perangkat keras telah ditingkatkan tetapi metode tetap. Juga biosis tidak selalu 64 bit atau 32 bit yang diprogram. Pendapat saya juga karena ingatan tidak selalu sama, bios harus ditempatkan pada segmen pertama yang sama. Cara kita melihat BIOS ditangani bukanlah alamat asli sepanjang waktu. Hanya mengajari saya ...

Agguro
sumber
2

setelah RESET cpu yang kompatibel dengan 8088/8086 mengeksekusi instruksi pada 0FFFF0, yaitu 16 byte di bawah batas 1 megabyte. biasanya ROM di lokasi ini (dalam implementasi PC) akan menjadi BIOS, jadi pada akhir BIOS ROM, ada lompatan ke awal ROM BIOS.

ditampilkan di sini: mulai vektor dan tanda tangan 'tanggal' di belakangnya, IBM 5150 PC 8KB dari tanggal bios dump: 10/19/1981

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

perhatikan bahwa pengalamatan adalah sebesar 8KB $ 2000 rom, yang menempatkan alamat awal (JMP jauh absolut, ke lokasi lain mana pun, dalam hal ini dalam 8KB rom itu sendiri, meskipun bukan alamat serendah mungkin dalam rom itu) pada $ FFFF: $ 0 tersegmentasi atau $ FFFF0 linier.

Adapun kompatibilitas: jika beberapa 'masa depan' atau prosesor saat ini 'mengharapkan' untuk memiliki F lebih banyak di depan alamat, itu tidak masalah. untuk kompatibilitas CPU yang lebih baru dalam sistem lama, garis alamat tambahan tetap tidak terhubung dan oleh karena itu data pada databus persis sama. selama bit paling tidak signifikan tetap FFFF0.

(dalam sistem dengan ram hanya 1mb dan rom diposisikan di akhir ram itu, dan tidak ada yang lain, itu akan dengan senang hati 'berpikir' itu berbicara ke alamat yang lebih tinggi namun mendapatkan data yang sama persis, karena implementasi tersebut belum pernah mendengar tentang garis alamat lebih tinggi dari A19)

perhatikan bahwa dunia bukan hanya 'pcs' ... PC ibm adalah 'kecelakaan', prosesor ini tidak pernah secara khusus dirancang untuk 'pcs' dan masuk ke banyak hal lebih dari sekadar pcs (seperti satelit, sistem senjata, dll). Mode terproteksi 32 dan 64bit biasanya -tidak- diinginkan. (Mode 8086 virtual jauh lebih menarik sebagai alasan untuk memilih versi yang lebih baru (386+) misalnya. oleh karena itu ada lebih banyak untuk 'kompatibilitas mundur' dari sekedar 'akan menjalankan dos'.

HRH Sven Olaf von CyberBunker
sumber
1

Motherboard memastikan bahwa instruksi pada reset vektor adalah lompatan ke lokasi memori yang dipetakan ke titik masuk BIOS. Lompatan ini secara implisit membersihkan alamat basis tersembunyi yang ada saat power up. Semua lokasi memori ini memiliki konten yang tepat yang dibutuhkan oleh CPU berkat peta memori yang disimpan oleh chipset. Mereka semua dipetakan ke memori flash yang mengandung BIOS karena pada saat ini modul RAM memiliki omong kosong acak di dalamnya.

viktorkh
sumber