Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用c表示内存_C_Pointers_Memory Management - Fatal编程技术网

用c表示内存

用c表示内存,c,pointers,memory-management,C,Pointers,Memory Management,我试图用C语言编写一个指令集模拟器来模拟运行ARM的机器。 我需要能够有效地表示4GB内存,经过一些挖掘,我找到了创建1024个指针数组的解决方案,每个指针指向一个4MB的块,该块在第一次使用时动态分配 #define MEMSIZE 1024 //1024 * 2Mb = 4Gb #define PAGESIZE 4194304 //4 Mb #define PAGEEXP 22 //2^PAGEEXP = PAGESIZE uint32_t* mem[MEMSIZE]

我试图用C语言编写一个指令集模拟器来模拟运行ARM的机器。 我需要能够有效地表示4GB内存,经过一些挖掘,我找到了创建1024个指针数组的解决方案,每个指针指向一个4MB的块,该块在第一次使用时动态分配

#define MEMSIZE 1024    //1024 * 2Mb = 4Gb
#define PAGESIZE 4194304    //4 Mb
#define PAGEEXP 22      //2^PAGEEXP = PAGESIZE

uint32_t* mem[MEMSIZE];
我的问题是如何访问内存的某个地址

我尝试将地址分解为索引和偏移量,如下所示,但对于索引和偏移量,这似乎只返回0。(memAdd是我试图访问的地址)

我拥有地址后用于读/写的函数如下:

void memWrite(uint32_t idx, uint32_t ofs, uint32_t val)
{
    if(mem[idx] == 0)
        mem[idx] = malloc(PAGESIZE);
    *(mem[idx] + ofs) = *(mem[idx] + ofs) & val;
}

uint32_t memRead(uint32_t idx, uint32_t ofs)
{
    if(mem[idx] == 0)
        return 0;
    else
        return *(mem[idx] + ofs);
}
这些在我的头脑中似乎是正确的,但是我仍然不能100%地适应指针,所以这可能是错误的


抱歉,如果这已经在某个地方讨论过了,但是我找不到任何与我需要的内容相关的内容(我的关键字非常广泛)

我认为
备忘录的价值计算不正确。例如,
PAGESIZE
表示的十进制值
4194304
是十六进制的
0x400000
,这意味着在按位AND运算之后,您只得到原始地址的第22位,而不是较低的22位。将该值添加到4MB页面数组指针实际上会将您发送到堆上已分配数组的末尾之外。将偏移量计算的掩码更改为
0x3FFFFF
,然后按位和原始内存地址更改掩码,以便计算页面中的正确偏移量。例如:

memIdx = memAdd >> PAGEEXP;
memOfs = memAdd & 0x3FFFFF;  //value of memOfs will be between 0 and 4194303

从逻辑上而不是从位的角度来看待它

每个页面有4194304字节

然后,从算术上讲,要将线性地址转换为(页,偏移量)对,您可以除以4194304得到页码,然后取余数得到页中的偏移量

page = address / PAGESIZE;
offset = address % PAGESIZE;
由于您希望有效地执行此操作,并且这些是2的幂,因此可以用PAGESIZE的以2为底的对数右移来代替PAGESIZE的除法,即22:

page = address >> PAGEEXP;
所以这部分代码是正确的。但是,要获得偏移量,您要做的是屏蔽掉除了刚从页码中移出的位之外的所有位。为此,您必须使用
PAGESIZE-1

offset = address & (PAGESIZE - 1);
这是因为在二进制文件中,您从一个看起来像这样的数字开始(其中p是页码位,o是偏移位):

您希望自己获取页码和偏移量。您显然希望右移22位以获得页码:

page = addresss >> 22 = 0000000000000000000000pppppppppp
但是如果您使用pagesize(二进制格式为000000000 100000000000000),那么答案中最多只有一个1位,它只会告诉您页码是奇数还是偶数。没用

您想要和使用的是比二进制0000000000 1111111111111少一位,因此:

  ppppppppppoooooooooooooooooooooo 
& 00000000001111111111111111111111
-----------------------------------
= 0000000000oooooooooooooooooooooo
这就是得到偏移量的方法


这是一条一般规则:如果N是2的整数幂,那么除以N与除以log(N)/log(2)的右移相同,这种除法的剩余部分通过与(N-1)进行ANDing得到。

这将满足您的要求。我用的是小号的。为了清楚起见,我省略了错误检查。它使用您使用索引器数组的方案

#include <cstdlib>
#include <cstdio>
#include <stdint.h>

#define NUMPAGE 1024
#define NUMINTSPERPAGE 4

uint32_t* buf;
uint32_t* idx[NUMPAGE];

void InitBuf()
{
    buf = (uint32_t*) calloc(NUMPAGE, NUMINTSPERPAGE * sizeof uint32_t );
    for ( size_t i = 0; i < NUMPAGE; i++ )
    {
        idx[i] = &buf[i * NUMINTSPERPAGE * sizeof uint32_t];
    }
}

void memWrite(size_t i, size_t ofs, uint32_t val)
{
    idx[i][ofs] = val;
}
uint32_t memRead(size_t i, size_t ofs)
{
    return idx[i][ofs];
}
int main()
{
    InitBuf();
    uint32_t val = 1243;
    memWrite(1, 2, val);
    printf("difference = %ld", val - memRead(1, 2));
    getchar();
}
#包括
#包括
#包括
#定义numpage1024
#定义NUMINTSPERPAGE 4
uint32_t*buf;
uint32_t*idx[NUMPAGE];
void InitBuf()
{
buf=(uint32_t*)calloc(NUMPAGE,NUMINTSPERPAGE*uint32_t的大小);
对于(大小i=0;i
如果
PAGESIZE
是2的幂,则只设置了1位。因此,将其与另一个值相加只能在结果中保留零或一位设置。两个可能的值。但您将它用作数组索引

另外,您的
memWrite(uint32\u t idx、uint32\u t of s、uint32\u t val)
函数始终在
val的值中进行AND运算。因此,例如,如果
val
uint32\u max
则对该函数的任何调用都将无效

最后,您不仅没有检查
malloc()
的失败结果,而且没有初始化返回的内存块

尝试这样的方法(不幸的是我一直无法测试它,我现在手头没有编译器)

enum{SIM_PAGE_BITS=22};//2^22=4MiB
枚举{SIM_MEM_PAGES=1024};//1024*4MiB=4GiB

enum{SIM_PAGE_SIZE=(1检查malloc失败-if(mem[idx]==NULL)…感谢您的回答。难以置信我犯了一个简单的错误,比如尝试和一个位。还对如何构造我的程序提供了一些很好的见解!
  ppppppppppoooooooooooooooooooooo 
& 00000000001111111111111111111111
-----------------------------------
= 0000000000oooooooooooooooooooooo
#include <cstdlib>
#include <cstdio>
#include <stdint.h>

#define NUMPAGE 1024
#define NUMINTSPERPAGE 4

uint32_t* buf;
uint32_t* idx[NUMPAGE];

void InitBuf()
{
    buf = (uint32_t*) calloc(NUMPAGE, NUMINTSPERPAGE * sizeof uint32_t );
    for ( size_t i = 0; i < NUMPAGE; i++ )
    {
        idx[i] = &buf[i * NUMINTSPERPAGE * sizeof uint32_t];
    }
}

void memWrite(size_t i, size_t ofs, uint32_t val)
{
    idx[i][ofs] = val;
}
uint32_t memRead(size_t i, size_t ofs)
{
    return idx[i][ofs];
}
int main()
{
    InitBuf();
    uint32_t val = 1243;
    memWrite(1, 2, val);
    printf("difference = %ld", val - memRead(1, 2));
    getchar();
}
enum { SIM_PAGE_BITS = 22 };   // 2^22 = 4MiB
enum { SIM_MEM_PAGES = 1024 }; // 1024 * 4MiB = 4GiB
enum { SIM_PAGE_SIZE = (1<<SIM_PAGE_BITS) };
enum { SIM_PAGE_MASK = SIM_PAGE_SIZE-1 };
enum { UNINITIALISED_MEMORY_CONTENT = 0 };
enum { WORD_BYTES = sizeof(uint32_t)/sizeof(unsigned char) };

#define PAGE_OFFSET(addr) (SIM_PAGE_MASK & (uint32_t)addr)
// cast to unsigned type to avoid sign extension surprises if addr<0
#define PAGE_NUM(addr) (((uint32_t)addr) >> SIM_PAGE_BITS)
#define IS_UNALIGNED(addr) (addr & (WORD_BYTES-1))

unsigned char* mem[MEMSIZE];

uint32_t memRead(uint32_t addr) {
    if (IS_UNALIGNED(addr)) return handle_unaligned_read(addr);
    const uint32_t page = PAGE_NUM(addr);
    if (mem[page]) {
        const unsigned char *p = mem[page] + PAGE_OFFSET(addr);
        return *(uint32_t*)p;
    } else {
        return UNINITIALISED_MEMORY_CONTENT;
    }
}

void memWrite(uint32_t addr, uint32_t val) {
    if (IS_UNALIGNED(addr)) return handle_unaligned_write(addr, val);
    const uint32_t page = PAGE_NUM(addr);
    if (!mem[page]) {
        if (val == UNINITIALISED_MEMORY_CONTENT) {
            return;
        }
        mem[page] = malloc(SIM_PAGE_SIZE);
        if (!mem[page]) {
            handle_out_of_memory();
        }
        // If UNINITIALISED_MEMORY_CONTENT is always 0 we can 
        // use calloc instead of malloc then memset.
        memset(mem[page], UNINITIALISED_MEMORY_CONTENT, SIM_PAGE_SIZE);
    } 
    const unsigned char *p = mem[page] + PAGE_OFFSET(addr);
    *(uint32_t*)p = val;
}