简体   繁体   中英

Accessing specific memory locations in C

In assembly language we have instructions like:

movl ax, [1000]

This allows us to access specific memory locations.

But in C can we do something similar to this?

I know inline assembly code using asm() will allow you to do this, but I would like to know about some C specific technique to achieve this.

I tried the following code and got segmentation error:

int *ptr=0xFE1DB124;
*ptr;

This again was confusing as the memory location was identified by the code given below:

int var;
printf("\nThe Address is %x",&var);

So the memory location is available, but I am still getting a segmentation fault.

Why?

Common C compilers will allow you to set a pointer from an integer and to access memory with that, and they will give you the expected results. However, this is an extension beyond the C standard, so you should check your compiler documentation to ensure it supports it. This feature is not uncommonly used in kernel code that must access memory at specific addresses. It is generally not useful in user programs.

As comments have mentioned, one problem you may be having is that your operating system loads programs into a randomized location each time a program is loaded. Therefore, the address you discover on one run will not be the address used in another run. Also, changing the source and recompiling may yield different addresses.

To demonstrate that you can use a pointer to access an address specified numerically, you can retrieve the address and use it within a single program execution:

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>


int main(void)
{
    //  Create an int.
    int x = 0;

    //  Find its address.
    char buf[100];
    sprintf(buf, "%" PRIuPTR, (uintptr_t) &x);
    printf("The address of x is %s.\n", buf);

    //  Read the address.
    uintptr_t u;
    sscanf(buf, "%" SCNuPTR, &u);

    //  Convert the integer value to an address.
    int *p = (int *) u;

    //  Modify the int through the new pointer.
    *p = 123;

    //  Display the int.
    printf("x = %d\n", x);

    return 0;
}

Obviously, this is not useful in a normal program; it is just a demonstration. You would use this sort of behavior only when you have a special need to access certain addresses.

For accessing Specific memory from user space, we have to map the memory Address to Programs Virtual Address using mmap() , the below C code shows the implementation:

Take a file " test_file " containing "ABCDEFGHIJ".

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>

int main(void)
{
    char *map_base_addr;  // Maping Base address for file
    int fd;         // File descriptor for open file
    int size = 10;

    fd= open("test_file", O_RDWR);  //open the file for reading and writing
    map_base_addr= mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);// Maping file into memory

    char *ch= map_base_addr;
    int i;

    /*Printing first 10 char*/
    for(i=0; i<size; i++)
            fputc(*(ch+i),stdout);
    printf("\n");

    *(ch+1) = 'b';
    *(ch+4) = 'z';
    *(ch+7) = 'x';

    /*Printing char after modification*/
    for(i=0; i<size; i++)
            fputc(*(ch+i),stdout);
    printf("\n");
    /* Finally unmap the file. This will flush out any changes. */
    munmap(map_base_addr, size);
    exit(0);
}

The output will be:

ABCDEFGHIJ
AbCDzFGxIJ

It works for me:

#include <stdio.h>

int main(int argc, char**argv) {
  int var = 7456;
  printf("Adress of var = %x, var=%d\n", &var, var);
  int *ptr = (int*)0x22cd28;
  printf(" ptr points to %x\n", ptr);
  *ptr = 123;
  printf("New value of var=%d\n", var);
  return 0;
}

Program output:

Adress of var = 22cd28, var=7456
 ptr points to 22cd28
New value of var=123

Note:

  1. The address is usually not the same on every execution. When I tried my example I had to run it three times before I got the address to match.

  2. char* can point to any adress (because sizeof (char) = 1). Pointers to larger objects must often be aligned on even adresses (usually one divisible by 4).

Your question doesn't really make much sense if you are running on linux/windows/mac/whatever

http://en.wikipedia.org/wiki/Virtual_memory

You can do that only if you are programming a device without virtual memory, or if you are programming the operating system itself.

Otherwise the addresses you see are not the "real" addresses on the RAM, the operating system translates them to real addresses and if there is not a map to translate your virtual address to a real one, then you can get a segmentation fault. Keep in mind that there are other reasons that can cause a segmentation fault.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM