If you want full access to all of the memory you need to boot in your app. I think you'll find that rather complicated.
One tool that does such is the memory testing app. under Linux. It's called memtest86+.
This requires you to start in 8086, and if you want access to all the RAM and have more than a 32 bit CPU can access, you need to switch to amd64 (64 bits CPU). Then you can check the entire memory.
The BIOS does that to detect all the memory banks and inform you about those (i.e. you have ways to get that information when your boot code starts allowing you to load your "OS"/code in a memory buffer that is available and large enough).
Under a modern OS (Windows 2k and newer, OS/X and newer, modern Unices such as Linux), the memory is managed using the kernel and all you see is virtual memory. This means the pointers you get in your apps under such a system have nothing to do with real memory pointers as you get on a boot. To do that, the CPU uses a unit called the MMU (or Memory Management Unit). In the old days, that was a separate processor. Now it's all in one.
Basic memory access is done using any instruction that allow for access to the memory. To load a value, you use the MOV
instruction:
MOV register, [address]
MOV register, [register]
In the first instruction, you use a fixed address.
In the second instruction, you loaded a register with an address and then load that value. That second solution is probably what you are looking for. You can then increase the register with an ADD
and access the next location. Something like this:
MOV r1, 123456 // load address
MOV r2, 256 // number of MOV to do
loop:
MOV r3, [r1]
...do something with r3?...
ADD r1, 4 // 4 for 32 bits, 8 for 64 bits, etc.
SUB r2, 1
JE loop
Here the r2
register is used to define how many reads to do.
In the old days, the Unix/Windows processes always started at a specific address, so you could can actually hard coded the 123456 address. Newer systems use ASLR which means the address changes on each restart of your application. That being said, you can capture the RIP register to get the current .text
pointer:
LEA rax, [rip]
With older processors (not 64 bits), you probably would need to use a CALL
:
CALL to_pop
to_pop:
POP eax
Since you don't really clearly define what memory range you want to read, I can't really help much more here, but the basic principal shown above should be sufficient to help you with your endeavor.