I know that each two letters in a hexdecimal address represents a byte, meaning that 0xFFFF is a 16bit address and can represent 65,536 bytes of memory, if the system is byte-addressable. However, if talking about a number of bits that is not a multiple of 8 (such as 14bit address), how can the operating system represnt these addresses?
0xFFFF -> 16 bit (e.g. Virtual memory address)
14 bit -> 0xFFF ? (Physical memory address)
One might say that the system has to be not byte addressable to access a not multiple of 8 address.. Then what will it be? I want the 16 bit of the virtual address to be byte addressable so we can easily access the data stored at that address, and I want to represent it in C code, but I have trouble representing the 14 bit physical memory addresses.
#define MAX_VIRT_ADDR ((0xffff) - 1) /* 65,536 */
#define MAX_PHYS_ADDR ((?) - 1) /* Max of 14bit physical memory space */
CodePudding user response:
The addresses are still just numbers. On a system with a 14-bit address bus, they go from 00000000000000 (binary) up to 11111111111111 (binary).
We can also write those numbers in decimal: they go from 0 up to 16383.
Or we can write them in hexadecimal: they go from 0 up to 3FFF (or 0000 up to 3FFF).
Or in octal: they go from 0 up to 37777 (or 00000 up to 37777).
Or in any other system we like.
Typically a system based on 8-bit bytes will allow 2 bytes to be used to access a memory address. If the system has some kind of memory protection unit, and it's configured appropriately, then addresses above 3FFF may cause some kind of invalid address exception (i.e. a segfault). Otherwise, usually the extra bits are just ignored, so that no matter whether the program accesses "address" 0x0005, 0x4005, 0x8005, or 0xC005, the actual address sent to the address bus is 5 (binary: 00000000000101).
CodePudding user response:
Your maximum "virtual" 16-bit address is 0xFFFF
. Your maximum "physical" 14-bit address is 0x3FFF
.
There's no rule that says address sizes have to be powers of 2, or that they have to be the same size as the words being addressed. It's massively more convenient to do things that way, but not required.
The old Motorola 68K had 32-bit words but a 24-bit address bus - address values were stored in 32-bit words with the upper 8 bits left unused.
As for mapping your 16-bit "virtual" address space onto a 14-bit "physical" address space, treat the upper two bits in the virtual address as a page number, treat the lower 14 bits as the offset into the page, map them directly to "physical" addresses. Store in a 16-bit type like uint16_t
, then use macros to extract page number and address like so:
#define PAGENO(vaddr) ((0xC000 & vaddr) >> 14)
#define PHADDR(vaddr) (0x3FFF & vaddr)
CodePudding user response:
It's simple: your 14bit address is
struct {
unsigned addr : 14;
};
You simply ignore 2 bits of the 16bit value.
Another way is to sign extend the 14bit value to 16bit. That's what 64bit systems like AMD64 or ARM64 do. They have 43-56 bits address space depending on the CPU and that is sign extended to 64bit. Addresses where the top bits aren't all 0 or all 1 are illegal.
CodePudding user response:
Exotic systems where bytes have more than 8 bits still (as far as I know) use the same addressing on byte level. Only the size of a byte changes. Certain digital signal processors like this do exist in the real world, although those would not run on an OS but get coded as "bare metal". Traditionally, DSP programming is also most often done in assembler rather than C.
So for any system with 16 bit wide address bus, you'll have:
#define MAX_VIRT_ADDR 0xffffu /* 65,535 */
#define MAX_PHYS_ADDR 0xffffu /* 65,535 */
And the size of one byte is irrelevant. If you'd design the system in any other way, you'd probably lose the advantage of having a larger byte size.