The Intel 432 could do that (1982). Unfortunately, the Intel 432 was also slow and very complex (it's the only architecture I'm aware of that was object oriented at the microcode level).
The Intel 80286 could also do that (some of the features of the Intel 432 found their way into the 80286) but no one who lived through those days wants to return to those days (small, compact, medium, large and huge memory models anyone?).
The Intel 80386 (and really, any Intel CPU that can still execute 16-bit code) can do that. But then you are programming a glorified 80286 and well ... see above.
But okay, you want more details? You have segment registers, CS, DS, ES, SS (and the 80386 give you a few more) that define the base address and limit. To get byte granularity, you are limited to 65536 bytes and you are dealing with a very odd-ball 32-bit address (16-bit segment, 16-bit offset) or a 48-bit address (16-bit segment, 32-bit offset limited to 65,535). If you want more memory per segment, you lose the byte granularity (promoting sloppy coding, etc).
The Intel 80286 could also do that (some of the features of the Intel 432 found their way into the 80286) but no one who lived through those days wants to return to those days (small, compact, medium, large and huge memory models anyone?).
The Intel 80386 (and really, any Intel CPU that can still execute 16-bit code) can do that. But then you are programming a glorified 80286 and well ... see above.
But okay, you want more details? You have segment registers, CS, DS, ES, SS (and the 80386 give you a few more) that define the base address and limit. To get byte granularity, you are limited to 65536 bytes and you are dealing with a very odd-ball 32-bit address (16-bit segment, 16-bit offset) or a 48-bit address (16-bit segment, 32-bit offset limited to 65,535). If you want more memory per segment, you lose the byte granularity (promoting sloppy coding, etc).
This is not an easy problem to solve.