Địa chỉ bộ nhớ

Trong máy tính, **địa chỉ bộ nhớ** là một tham chiếu đến một vị trí bộ nhớ cụ thể được phần mềm và phần cứng sử dụng ở nhiều tầng khác nhau. Địa chỉ bộ nhớ là các dãy chữ số có độ dài cố định, theo quy ước được hiển thị và xử lý như số nguyên không dấu. Ngữ nghĩa số như vậy được dựa trên các đặc điểm của CPU (chẳng hạn như con trỏ lệnh và thanh ghi tăng địa chỉ), và cũng được dựa trên việc sử dụng bộ nhớ như một mảng được các ngôn ngữ lập trình khác nhau tán thành.

## Các loại

### Địa chỉ thực
Bộ nhớ chính của máy tính bao gồm nhiều **ô nhớ**. Mỗi ô nhớ có một **địa chỉ vật lý** là một mã. CPU (hoặc thiết bị khác) có thể sử dụng mã này để truy cập vị trí ô nhớ tương ứng. Thường chỉ có phần mềm hệ thống, tức là BIOS, hệ điều hành và một số chương trình tiện ích chuyên dụng (ví dụ: chương trình kiểm tra bộ nhớ) sử dụng địa chỉ bộ nhớ vật lý trong các toán hạng hoặc thanh ghi trong mã máy để CPU ra lệnh cho bộ điều khiển bộ nhớ sử dụng bus bộ nhớ hoặc bus hệ thống (đôi khi là bus điều khiển, bus địa chỉ và bus dữ liệu riêng biệt) thực thi các lệnh của chương trình. Bus của bộ điều khiển bộ nhớ bao gồm một số đường song song, mỗi đường được biểu diễn bằng một chữ số nhị phân (bit). Độ rộng của bus, kéo theo số đơn vị lưu trữ có thể gán địa chỉ và số bit trong mỗi đơn vị, là khác nhau giữa các máy tính.

### Địa chỉ logic
Chương trình máy tính sử dụng địa chỉ bộ nhớ để thực thi mã máy và lưu trữ, truy xuất dữ liệu. Trong các máy tính sơ khai, địa chỉ vật lý và logic tương ứng với nhau, nhưng kể từ khi bộ nhớ ảo ra đời, hầu hết các chương trình ứng dụng không thấy được địa chỉ vật lý. Thay vào đó, chúng sử dụng các địa chỉ **logic**, hoặc địa chỉ ảo, thông qua đơn vị quản lý bộ nhớ của máy tính và cách hệ điều hành gán bộ nhớ; xem bên dưới.

## Đơn vị phân giải địa chỉ
Hầu hết các máy tính hiện đại đều sử dụng địa chỉ byte. Mỗi địa chỉ xác định một byte (tám bit) duy nhất của thiết bị luu trữ. Dữ liệu lớn hơn một byte có thể được lưu trữ trong một chuỗi các địa chỉ liên tiếp. Có các máy tính sử dụng địa chỉ word, trong đó đơn vị lưu trữ nhỏ nhất có thể gán địa chỉ là một word của bộ xử lý. Ví dụ, máy tính mini Data General Nova, các máy vi tính Texas Instruments TMS9900 và National Semiconductor IMP-16 sử dụng word 16 bit. Nhiều mainframe 36 bit (ví dụ: PDP-10) sử dụng địa chỉ word (18 bit), không phải *địa chỉ byte*, do đó không gian địa chỉ có 218 word (36 bit), tức là khoảng 1 megabyte bộ nhớ. Khả năng gán địa chỉ cho bộ nhớ phụ thuộc vào kích thước tính theo bit của bus địa chỉ - càng sử dụng nhiều bit, máy tính càng có nhiều địa chỉ. Ví dụ, một máy *địa chỉ byte* (8 bit) có bus địa chỉ 20 bit (ví dụ: Intel 8086) có thể gán địa chỉ cho 220 (1.048.576) byte hay một MiB bộ nhớ, trong khi bus 32 bit (ví dụ: Intel 80386) gán địa chỉ cho 232 byte (4.294.967.296) hoặc 4 GiB. Trái lại, máy *địa chỉ word* (36 bit) với bus địa chỉ 18 bit có thể gán địa chỉ cho 218 (262,144) ô nhớ 36 bit (9,437,184 bit), tương đương với 1.179.648 byte, hay 1.125 MiB - nhiều hơn một chút so với 8086.

Một số máy tính cũ hơn (máy tính sử dụng hệ thập phân), sử dụng *địa chỉ thập phân*. Ví dụ, mỗi địa chỉ trong bộ nhớ lõi từ của IBM 1620 có dạng một BCD 6 bit, bao gồm một bit chẵn lẻ, bit cờ và bốn bit số. IBM 1620 sử dụng địa chỉ thập phân gồm 5 chữ số, vì vậy về lý thuyết, địa chỉ cao nhất có thể là 99.999. Trên thực tế, CPU của nó hỗ trợ 20.000 địa chỉ và có thể thêm vào tối đa hai đơn vị bộ nhớ ngoài tùy ý, mỗi đơn vị hỗ trợ 20.000 địa chỉ, với tổng số địa chỉ là 60.000 (00000–59999).

### Kích thước word và kích thước địa chỉ
Kích thước word là một đặc trưng của kiến trúc máy tính. Nó biểu thị số bit mà CPU có thể xử lý tại một thời điểm. Các bộ xử lý hiện đại, kể cả các hệ thống nhúng, thường có kích thước word là 8, 16, 24, 32 hoặc 64 bit; hầu hết các máy tính thông thường hiện nay sử dụng 32 hoặc 64 bit. Nhiều kích thước khác nhau đã được sử dụng trong quá khứ, bao gồm 8, 9, 10, 12, 18, 24, 36, 39, 40, 48 và 60 bit.

Thông thường, khi đề cập đến *kích thước word* của một máy tính hiện đại, người ta còn đang mô tả kích thước của không gian địa chỉ trên máy tính đó. Ví dụ, một máy tính được gọi là "32-bit" cũng thường chấp nhận địa chỉ 32-bit; một máy tính 32 bit *địa chỉ byte* có thể gán địa chỉ cho 232 = 4.294.967.296 byte bộ nhớ hay 4 gibibyte (GiB). Điều này cho phép một địa chỉ bộ nhớ được lưu trữ hoàn toàn trong một word.

Tuy nhiên, điều này không phải lúc nào cũng đúng. Máy tính có thể có địa chỉ bộ nhớ lớn hơn hoặc nhỏ hơn kích thước word của nó. Ví dụ, nhiều bộ xử lý 8 bit, chẳng hạn như MOS Technology 6502, hỗ trợ địa chỉ 16 bit - nếu không, chúng sẽ bị giới hạn ở 256 byte bộ nhớ. Intel 8088 và Intel 8086 16 bit hỗ trợ địa chỉ 20 bit thông qua phân đoạn, cho phép chúng truy cập 1 MiB thay vì 64 KiB bộ nhớ. Tất cả các bộ xử lý Intel Pentium kể từ Pentium Pro đều có Phần mở rộng địa chỉ vật lý (PAE), hỗ trợ map từ địa chỉ vật lý 36 bit sang địa chỉ ảo 32 bit. Nhiều bộ xử lý thời đầu chứa 2 địa chỉ trong mỗi word, chẳng hạn như các bộ xử lý 36-bit.

Về lý thuyết, máy tính 64 bit địa chỉ byte thời hiện đại có thể sử dụng 264 byte(16 exbibyte) bộ nhớ, nhưng trên thực tế, dung lượng bộ nhớ bị giới hạn bởi CPU, bộ điều khiển bộ nhớ hoặc thiết kế của bảng mạch in (ví dụ: số lượng đầu nối bộ nhớ vật lý hoặc dung lượng bộ nhớ hàn chết).

## Nội dung của từng vị trí bộ nhớ
Mỗi ô nhớ trong một máy tính chương trình lưu trữ chứa một số nhị phân hoặc số thập phân. Việc diễn giải nó dưới dạng dữ liệu thuộc một kiểu dữ liệu hay một lệnh, và việc sử dụng nó, được xác định bởi các lệnh truy xuất và thay tác trên nó.

Một số lập trình viên thời đầu trộn các lệnh và dữ liệu trong word để tiết kiệm bộ nhớ, thời mà nó còn đắt tiền: Manchester Mark 1 có khoảng trống trong các word 40 bit để lưu trữ các bit dữ liệu nhỏ, vì bộ xử lý của nó bỏ qua một phần nhỏ ở giữa một word. Các chương trình tự sao chép như vi rút đôi khi coi bản thân chúng như dữ liệu và đôi khi là các lệnh. Mã tự sửa đổi ngày nay thường không được dùng nữa, vì rất khó để kiểm tra và bảo trì đổi lấy việc tiết kiệm một vài byte, và cũng có thể cho kết quả không chính xác do giả định của trình biên dịch hoặc bộ xử lý về trạng thái của máy, nhưng đôi khi vẫn được sử dụng một cách có chủ ý nếu cực kỳ thận trọng.

### Không gian địa chỉ trong lập trình ứng dụng
Trong môi trường đa nhiệm hiện đại, một tiến trình ứng dụng thường có trong không gian địa chỉ của nó các khối bộ nhớ thuộc các loại sau:

* **[[Ngôn ngữ máy|Mã máy]]**, bao gồm:
** mã của bản thân chương trình (trước đây được gọi là *đoạn mã* hoặc *đoạn văn bản*);
** thư viện dùng chung.
* **[[Dữ liệu (máy tính)|Dữ liệu]]**, bao gồm:
** dữ liệu đã khởi tạo (đoạn dữ liệu);
** biến chưa được khởi tạo (nhưng được cấp phát);
** ngăn xếp thời gian chạy;
** đống;
** bộ nhớ dùng chung và các tệp mà bộ nhớ được map vào.

Một số phần của không gian địa chỉ có thể không được gán vào đâu.

## Phương án đánh địa chỉ
Một chương trình máy tính có thể truy cập một địa chỉ được cung cấp **một cách rõ ràng** - trong lập trình cấp thấp, địa chỉ này thường được gọi là địa chỉ tuyệt đối hoặc đôi khi là **địa chỉ cụ thể**, hay còn gọi là kiểu dữ liệu con trỏ trong các ngôn ngữ cấp cao hơn. Nhưng một chương trình cũng có thể sử dụng địa chỉ tương đối để chỉ định một vị trí tương đối so với một vị trí khác (*địa chỉ cơ sở*). Còn có nhiều chế độ gán địa chỉ gián tiếp khác.

Ánh xạ từ địa chỉ logic vào bộ nhớ vật lý và bộ nhớ ảo cũng làm tăng thêm một số tầng indirection; xem bên dưới.

## Các mô hình bộ nhớ
Nhiều lập trình viên ưa thích cách gán địa chỉ bộ nhớ sao cho không có sự khác biệt giữa vùng mã và vùng dữ liệu (xem ở trên), cũng như giữa bộ nhớ vật lý và bộ nhớ ảo (xem bên dưới) - nói cách khác, các con trỏ như nhau về giá trị trỏ tới đúng cùng một byte của RAM.

Tuy nhiên, nhiều máy tính thời đầu không hỗ trợ *mô hình bộ nhớ phẳng* như vậy - đặc biệt, các máy kiến trúc Harvard bắt bộ nhớ chương trình phải hoàn toàn tách biệt với bộ nhớ dữ liệu. Nhiều bộ xử lý tín hiệu số hiện đại (chẳng hạn như Motorola 56000) có ba vùng nhớ riêng biệt - bộ nhớ chương trình, bộ nhớ hệ số và bộ nhớ dữ liệu. Một số lệnh thường dùng tìm nạp đồng thời từ cả ba vùng - ít vùng nhớ hơn (mặc dù tổng số byte bộ nhớ vẫn như vậy) sẽ làm cho các lệnh đó chạy chậm hơn.

### Các mô hình bộ nhớ trong kiến trúc x86
Các máy tính x86 đầu tiên sử dụng loại địa chỉ phân đoạn gồm hai số: phân đoạn bộ nhớ + độ lệch trong phân đoạn đó.

Một số phân đoạn có thể ngầm định là *phân đoạn mã*, dành riêng cho lệnh, hoặc *phân đoạn ngăn xếp* hoặc *phân đoạn [[Dữ liệu (máy tính)|dữ liệu]]* bình thường. Mặc dù cách sử dụng khác nhau, việc các phân đoạn này không có cơ chế bảo vệ bộ nhớ khác nhau phản ánh điều này. Trong mô hình bộ nhớ tuyến tính tất cả các phân đoạn (hay thanh ghi phân đoạn) thường được đặt bằng 0, và độ lệch (địa chỉ offset) là biến số.

## Xem thêm

* Mô hình bộ nhớ (lập trình)
* Cấp phát bộ nhớ
* Thanh ghi địa chỉ
* Địa chỉ cơ sở
* Độ lệch (khoa học máy tính)
* Endianness
* Đơn vị quản lý bộ nhớ (MMU)
* Page table
* Bảo vệ bộ nhớ
* Phân đoạn bộ nhớ
* Ngôn ngữ lập trình cấp thấp

## Chú thích