精华内容
下载资源
问答
  • 游戏作弊-内存读写原理

    千次阅读 多人点赞 2020-08-02 19:55:04
    第一课我们浅解安卓ROOT手机如何修改游戏内存 在当前流行的FPS,MOBA游戏中,我们几乎都能看到游戏外挂的身影,在FPS游戏中,可见变态功能层出不穷,例如加速,锁血 遁地,飞天,路飞,无后座,范围伤害等…,然而在...

    第一课我们浅解安卓ROOT手机如何修改游戏内存

    在当前流行的FPS,MOBA游戏中,我们几乎都能看到游戏外挂的身影,在FPS游戏中,可见变态功能层出不穷,例如加速,锁血 遁地,飞天,路飞,无后座,范围伤害等…,然而在MOBA游戏中,最常见的只有透视和自瞄。

    切入正题,如何操作内存?在安卓中,我们可直接操作/proc/${pid}/mem

    使用C语言pread函数

    ssize_t pread(int fd, void *buf, size_t count, off_t offset);
    

    简单解释下这个函数

    fd:要读取数据的文件描述符
    buf:数据缓存区指针,存放读取出来的数据
    count:读取数据的字节数
    offset:读取的起始地址的偏移量,读取地址=文件开始+offset。注意,执行后,文件偏移指针不变
    

    还有另一个函数:pread64
    很多人不知道pread64和pread的区别,其实pread64是用64位定位方式,用于对大文件的支持,与pread不同的是,pread64的偏移量参数为off64_t,而不是off_t

    读写游戏内存最重要的是获取游戏进程的PID,什么是PID?PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID。进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在android系统中一般不会把已经kill掉的进程ID重新分配给新的进程,新产生进程的进程号,一般比产生之前所有的进程号都要大。

    那么问题来了,如何获取游戏pid?

    第一种方式:
    遍历/proc/${pid}/cmdline
    cmdline文件储存的是当前进程的启动名(包名)

    直接贴代码:

    pid_t GetProcessID(const char *process_name)
    {
    	int id;
    	pid_t pid = -1;
    	DIR *dir;
    	FILE *fp;
    	char filename[32];
    	char cmdline[256];
    	struct dirent *entry;
    	if (process_name == NULL)
    	{
    		return -1;
    	}
    	dir = opendir("/proc");
    	if (dir == NULL)
    	{
    		return -1;
    	}
    	while ((entry = readdir(dir)) != NULL)
    	{
    		id = atoi(entry->d_name);
    		if (id != 0)
    		{
    			sprintf(filename, "/proc/%d/cmdline", id);
    			fp = fopen(filename, "r");
    			if (fp)
    			{
    				fgets(cmdline, sizeof(cmdline), fp);
    				fclose(fp);
    				if (strcmp(process_name, cmdline) == 0)
    				{
    					pid = id;
    					break;
    				}
    			}
    		}
    	}
    	closedir(dir);
    	return pid;
    }
    

    第二种方式:使用shell命令的pidof

    char *shell(const char *command)
    {
    	FILE *fp = NULL;
    	char line[256] = { };
    	char *result = (char *)malloc(2048);
    	memset(result, 0, sizeof(result));
    	fp = popen(command, "r");
    	while (fgets(line, sizeof(line), fp) != NULL)
    	{
    		strncat(result, line, strlen(line));
    	}
    	pclose(fp);
    	return result;
    }
    
    pid_t GetProcessID(char *process_name)
    {
        char cmd[256] = {0};
        sprintf(cmd,"su -c pidof %s",process_name);
    	char *id = shell(cmd);
    	return strlen(id) == 0 ? -1 : atoi(id);
    }
    

    如何读内存:

    char filename[256] = {0};
    sprintf(filename,"/proc/%d/mem",pid);//pid为获取到的游戏pid
    int fd = open(filename,O_RDWR | O_SYNC);//以可读写(O_RDWR)且同步(O_SYNC)的方式打开文件
    int buf = 0;
    pread(fd,&buf,sizeof(buf),内存地址);
    printf("value:%d\n",buf);
    

    学会了读取内存,那如何写入内存呢?
    这时候需要用到另一个函数:pwrite
    pwrite的参数和pread一样,我就不讲解了

    char filename[256] = {0};
    sprintf(filename,"/proc/%d/mem",pid);//pid为获取到的游戏pid
    int fd = open(filename,O_RDWR | O_SYNC);//以可读写(O_RDWR)且同步(O_SYNC)的方式打开文件
    int wbuf = 666;
    pwrite(fd,&wbuf,sizeof(wbuf),内存地址);//向指定地址写入指定值(修改地址的值)
    

    根据上两段代码,我们可以发现一个知识点:内存地址

    这个内存地址如何获取?
    在proc文件系统中,有一个内存段映射文件:/proc/${pid}/maps
    打开这个文件,我们可以得到以下结构:

    f1ed1000-f1ed9000 r--p 00000000 fc:02 3092        /system/lib/libsensor.so
    f1ed9000-f1edf000 r-xp 00008000 fc:02 3092        /system/lib/libsensor.so
    f1edf000-f1ee0000 rw-p 0000e000 fc:02 3092        /system/lib/libsensor.so
    f1ee0000-f1ee2000 r--p 0000f000 fc:02 3092        /system/lib/libsensor.so
    f1ee2000-f1ee3000 rw-p 00000000 00:00 0           [anon:.bss]
    

    关于maps文件各列解释,可以参考
    https://blog.csdn.net/lijzheng/article/details/23618365

    可以看出,第一列既为我们需要的游戏内存地址。
    现在问题来了,像gg修改器,我们如何在内存里搜索一个值呢?

    这时候又涉及一个知识点:值所在的内存范围

    为了方便,我们可以使用GG修改器的内存范围

    struct Memory
    {
    	int A = 32;
    	int As = 524288;
    	int B = 131072;
    	int Xa = 16384;
    	int Xs = 32768;
    	int Ca = 4;
    	int Cb = 16;
    	int Cd = 8;
    	int Ch = 1;
    	int J = 65536;
    	int Jh = 2;
    	int O = -2080896;
    	int Ps = 262144;
    	int S = 64;
    	int V = 1048576;
    } MemRange;
    
    
    int getMemRange(char *str)
    {
    	if (strlen(str) == 0)
    		return MemRange.A;
    	if (strstr(str, "/dev/ashmem/") != NULL)
    		return MemRange.As;
    	if (strstr(str, "/system/fonts/") != NULL)
    		return MemRange.B;
    	if (strstr(str, "/data/app/") != NULL)
    		return MemRange.Xa;
    	if (strstr(str, "/system/framework/") != NULL)
    		return MemRange.Xs;
    	if (strcmp(str, "[anon:libc_malloc]") == 0)
    		return MemRange.Ca;
    	if (strstr(str, ":bss") != NULL)
    		return MemRange.Cb;
    	if (strstr(str, "/data/data/") != NULL)
    		return MemRange.Cd;
    	if (strstr(str, "[anon:dalvik") != NULL)
    		return MemRange.J;
    	if (strcmp(str, "[stack]") == 0)
    		return MemRange.S;
    	if (strcmp(str, "/dev/kgsl-3d0") == 0)
    		return MemRange.V;
    	return MemRange.O;
    }
    
    

    如何搜索值:
    通过遍历内存段映射地址,判断值是否为搜索的值
    例如f1ed1000-f1ed9000,我们需要遍历f1ed1000到f1ed9000的所有地址的值来判断

    直接上代码:

    long start = 0xf1ed1000;
    long end = 0xf1ed9000;
    int value = 1;//我们要搜索的值
    char filename[256] = {0};
    sprintf(filename,"/proc/%d/mem",pid);
    int fd = open(filename,O_RDWR | O_SYNC);
    long size = end - start;
    int count = 0;//计数
    void *buf = calloc(1, size);
    pread64(fd,buf,size,start);
    int block_size = sizeof(int);
    for(int i = 0;i<size;i+=block_size)
    {
    	int search_value = *(int*)(buf + i);
        if(search_value == value)
        {
            //搜索到数值
            printf("index:%d address:%lx value:%d\n",i,start + i,search_value);
            count++;
        }
    }
    printf("搜索到:%d个数值\n",count);
    

    现在搜索数值会了,修改数值不就迎刃而解了吗?

    今天的教程结束,有不懂的可以私信问我。手打代码不易,看完加个关注,持续更新游戏作弊教程

    展开全文
  • 磁盘和内存读写简单原理

    千次阅读 2019-08-15 11:32:25
    当程序要读取的数据时传入内存地址(行地址+列地址),如果数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,通过柱面号,磁头号,扇区号定位磁盘位置,找到数据的起始位置并向后连续读取一页...

    当程序要读取的数据时传入内存地址(行地址+列地址),如果数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,通过柱面号,磁头号,扇区号定位磁盘位置,找到数据的起始位置并向后连续读取一页或几页载入内存中。

     


    我们在程序中的数据处理主要是操作磁盘和内存,硬盘是磁盘里面最常用的一种.以前有所谓的软盘,也是磁盘的一种,原理和硬盘是一样的.都是利用磁性物质的特性来保存信息.磁盘的原理就是利用电磁转换,学物理时我们知道电可以使物质带上磁性,而金属在磁场运动时切割磁感线时会产生电流.磁盘上有很多微粒的磁粉.当写通过磁头写数据时,磁头中的电流会导致磁粉极化,改变方向.读数据时,导体磁头经过磁粒的区域时会产生电流. 反正大概意思就是这样.

    硬盘的存储数据原理:
    我们知道信息存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片。假设,你用显微镜把盘片放大,会看见盘片表面凹凸不平,凸起的地方被磁化,凹的地方是没有被磁化;凸起的地方代表数字1(磁化为1),凹的地方代表数字0。因此硬盘可以以二进制来存储表示文字、图片等信息。


    内存存储数据原理:
    而内存的原理就完全不同,内存是晶体管制作的(CPU也是晶体管做的),而晶体管的特性就是我们平时常说的用开关的开和关来表示1,0.
    通过一些门电路的组合可用来表示数字和实现复杂的逻辑功能.而内存主要是用来临时保存数据.CPU就是处理一些逻辑关系.

    晶体管由于必须得通电,然后用电流的有无状态来表示信息,充放电后电荷的多少(电势高低)分别对应二进制数据0和1,所以只有通电的时候可以保存数据,电一断内存里的晶体管状态就处未知状态就啥用处也没了.而磁盘断电后磁性物质还会一直保持原样.

    我们知道访问磁盘时就通过磁头去指到固定的地方然后读取数据.不过内存就不一样,不需要啥磁头去读取数据,它是有数据总线连接,我们是通过总线去读取内存的数据.

    磁盘的读写原理:(柱面号,磁头号,扇区号)


    确定磁盘地址(柱面号,磁头号,扇区号),内存地址(源/目):

           当需要从磁盘读取数据时,系统会将数据逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读的数据在哪个磁道,哪个扇区。

    为了读取这个扇区的数据,需要将磁头放到这个扇区上方,为了实现这一点:

             1)首先必须找到柱面,即磁头需要移动对准相应磁道,这个过程叫做寻道,所耗费时间叫做寻道时间,

             2)然后目标扇区旋转到磁头下,即磁盘旋转将目标扇区旋转到磁头下。这个过程耗费的时间叫做旋转时间。

    即一次访盘请求(读/写)完成过程由三个动作组成:
           1)寻道(时间):磁头移动定位到指定磁道 
           2)旋转延迟(时间):等待指定扇区从磁头下旋转经过 
           3)数据传输(时间):数据在磁盘与内存之间的实际传输

    内存的读写原理:(行地址+列地址)

    内存地址

    内存中的cell按矩阵形排列,每一行和每一列都会有一个对应的行地址线路(正规叫法叫做word line)和列地址线路(正规叫法是bit line),每个具体的cell就挂接在这样的行地址线路和列地址线路上,对应一个唯一的行号和列号,把行号和列号组合在一起,就是内存的地址。


    上图是Thaiphoon Burner的一个SPD dump,每个地址是一个字节。不过我们可以把这些数据假设成只有一个bit,当成是一个简单的内存地址表,左边竖着的是行地址,上方横着的是列地址。例如我们要找第七行、倒数第二列(地址为7E)的数据,它就只有一个对应的值:FD。当然了,在内存的cell中,它只能是0或者1。

    寻址

    数据要写入内存的一个cell,或者从内存中的一个cell读取数据,首先要完成对这个cell的寻址。寻址的过程,首先是将需要操作的cell的对应行地址信号和列地址信号输入行/列地址缓冲器,然后先通过行解码器(Row Decoder)选择特定的行地址线路,以激活特定的行地址。每一条行地址线路会与多条列地址线路和cell相连接,为了侦测列地址线路上微弱的激活信号,还需要一个额外的感应放大器(Sense Amplifier)放大这个信号。当行激活之后,列地址缓冲器中的列地址信号通过列解码器(Column Decoder)确定列地址,并被对应的感应放大器通过连接IO线路,这样cell就被激活,并可供读写操作,寻址完成。从行地址激活,到找到列地址这段时间,就是tRCD。

    从内存读取到磁盘预读
      由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理:

      当一个数据被用到时,其附近的数据也通常会马上被使用。

      程序运行期间所需要的数据通常比较集中。

      由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

      预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

    参考:
    http://blog.csdn.net/hguisu/article/details/7408047
    硬盘的读写原理
    http://www.cnblogs.com/QQParadise/articles/2430204.html
    内存的工作原理及时序介绍
    http://blog.csdn.net/lujiandong1/article/details/44569161

    展开全文
  • 内存读写驱动的源码(C++)
  • X64驱动读写内存源码

    2020-11-20 10:47:32
    X64驱动读写内存源码,驱动基于VS2019编写,只支持64位,驱动未签名需要自行开启测试模式加载,R3层基于易语言编写无模块 编译即可用,所有源码都在压缩包里自行下载即可
  • Java文件读写原理和虚拟内存

    千次阅读 2019-04-10 08:50:57
    这里用户空间相当于储户,内核空间相当于银行职员,而硬盘相当于金库,也就是用户空间中的进程没法直接操作读写硬盘中的数据,我们需要通过内核空间来处理,这样对于这两个概念应该会容易理解些。 空间 ...

      后面打算系统性的介绍下NIO和Netty的内容,因为这块内容也是每个程序员必须要掌握的内容,而在介绍NIO之前我们需要先了解下一些前置的知识

    1.内核空间和用户空间

      这两个概念对于初次接触的小伙伴来说并不是很好理解,举个简单例子如下图:

    在这里插入图片描述

      上图中的储户是没法直接从金库中存钱获取取钱的,如果这么做了,那么就非法了。这里用户空间相当于储户,内核空间相当于银行职员,而硬盘相当于金库,也就是用户空间中的进程没法直接操作读写硬盘中的数据,我们需要通过内核空间来处理,这样对于这两个概念应该会容易理解些。

    空间描述
    用户空间是非特权区域,在该区域执行的代码不能直接访问硬件设备,常规进程就在本区域执行,JVM就是常规进程,所以JVM进程驻守在用户空间
    内核空间是操作系统所在区域,有特别的权利:能与设备控制器通讯,控制着用户区域进程的运行状态等等,最重要的是,所有I/O都直接或间接的通过内核空间

    2.普通IO操作

      了解了用户空间和内核空间的概念和作用后我们来看下普通IO的执行原理。

    在这里插入图片描述

      根据上图,当进程请求一个I/O操作,它会执行一个系统(open() , read() , writer() , close())调用将控制权移交给内核。当内核以这种方式被调用,它随即采取任何必要步骤,找到进程所需数据,并把数据传送到用户空间内指定的缓冲区中,这时常规进程就可以对缓冲区中的数据处理操作了,而内核试图对数据进行高速缓存或预读取,因此进程所需数据可能已经在内核空间里了,如果是这样,该数据只需简单地拷贝出来即可,如果数据不在内核空间,则进程被挂起,内核着手把数据读进内场。

    问题

      数据从内核空间拷贝到用户空间似乎多余,为什么不直接让磁盘把数据送到用户空间的缓冲区呢?

    1. 硬盘通常不能直接访问用户空间
    2. 磁盘基于块存储的硬件设备操作的固定大小的数据块,用户进程请求的可能是任意大小或者非对齐的数据块,在这两者数据交互过程中内核负责数据的分解、再组合工作,起到一个中间人的角色。

    3.虚拟内存

      通过上面的介绍,我们知道当应用程序需要读取文件的时候,内核首先通过DMA技术将文件内容从磁盘读入内核中的buffer,然后Java应用进程再从内核的buffer将数据读取到应用程序的buffer。也就是有两次的文件复制,为了提升I/O效率和处理能力,操作系统采用虚拟内存的机制。虚拟内存意为使用虚假(或虚拟)地址取代物理(硬件RAM)内存地址。这样做好处颇多,总结起来可分为两大类:

    1. 一个以上的虚拟地址可指向同一个物理内存地址。
    2. 虚拟内存空间可大于实际可用的硬件内存

    在这里插入图片描述

      这样做的好处是省去了内核与用户空间的往来拷贝。

    3.1 一个以上的虚拟地址可指向同一个物理内存地址

      在进行IO操作时就可以将用户空间的buffer区和内核空间的buffer区指向同一个物理内存。这样用户空间的程序就不需要再去内核空间再取回数据,而是可以直接访问,节省内存空间。

    在这里插入图片描述

    3.2 虚拟内存空间可大于实际可用的硬件内存

      当用户程序访问内存地址时,一般的操作如下:首先虚拟内存系统会到物理内存去查找该虚拟地址是否存在。如果存在,如A1,则直接从物理内存中读取;如果不存在,如A4则会抛出一个信号。这时虚拟内存系统会去磁盘空间中找,找到后再按一定的策略,将其置入到内存中,如将B2和A4交换。然后由用户程序就可以使用A4中的数据。这样就保证了用户程序可以读取一些大型的文件。

    在这里插入图片描述

      从本质上说,物理内存充当了分页区高速缓存;而所谓分页区,即从物理内存置换出来,转而存储于磁盘上的内存页面.

      把内存页大小设定为磁盘块大小的倍数,这样内核就可直接向磁盘控制硬件发布命令,把内存页写入磁盘,在需要时再重新装入。结果是,所有磁盘 I/O 都在页层面完成。对于采用分页技术的,现代操作系统而言,这也是数据在磁盘与物理内存之间往来的唯一方式

    在这里插入图片描述

    3.3内存管理单元

      现代 CPU 包含一个称为内存管理单元(MMU)的子系统,逻辑上位于CPU 与物理内存之间。该设备包含虚拟地址向物理内存地址转换时所需映射信息。当 CPU 引用某内存地址时,MMU负责确定该地址所在页(往往通过对地址值进行移位或屏蔽位操作实现),并将虚拟页号转换为物理页号(这一步由硬件完成,速度极快)。如果当前不存在与该虚拟页形成有效映射的物理内存页,MMU会向CPU 提交一个页错误。

    在这里插入图片描述

      页错误随即产生一个陷阱(类似于系统调用),把控制权移交给内核,附带导致错误的虚拟地址信息,然后内核采取步骤验证页的有效性。内核会安排页面调入操作,把缺失的页内容读回物理内存。这往往导致别的页被移出物理内存,好给新来的页让地方。在这种情况下,如果待移出的页已经被碰过了(自创建或上次页面调入以来,内容已发生改变),还必须首先执行页面调出,把页内容拷贝到磁盘上的分页区。
      如果所要求的地址不是有效的虚拟内存地址(不属于正在执行的进程的任何一个内存段),则该页不能通过验证,段错误随即产生。于是,控制权转交给内核的另一部分,通常导致的结果就是进程被强令关闭。
      一旦出错的页通过了验证,MMU 随即更新,建立新的虚拟到物理的映射(如有必要,中断被移出页的映射),用户进程得以继续。造成页错误的用户进程对此不会有丝毫察觉,一切都在不知不觉中进行

    展开全文
  • 10分钟看懂内存的实现原理

    千次阅读 多人点赞 2019-11-06 13:57:46
    内存最小单位是一些类似于二极管这样的东西,它能存储一个电状态,高或低,可表示1或0; -这些单元经过组织起来保存数据,组织的方法是8个编成一个字节,4个字节一个字,每组数据都可以读写; -这些单元按照顺序排放...

     

    内存最小单位是一些类似于二极管这样的东西,它能存储一个电状态,高或低,可表示1或0;
    -这些单元经过组织起来保存数据,组织的方法是8个编成一个字节,4个字节一个字,每组数据都可以读写;
    -这些单元按照顺序排放后用地址编号,按照地址可访问其中的任一个字、字节;
    -这些电路访问时由两组数据连线:地址线和数据线,比如都是32位的,地址线描述要访问的具体单元,数据线存放要给这个单元赋值的数据(写访问)或读出的数据(读访问);
    -这些单元上电时才能保持状态,所以内存你一掉电(关机),其中的数据就丢失了。

     

    硬盘存储器中,所存储二进制信息的两种状态是用什么表示的?

    用两个不同方向的磁化,来表示数码0和1。
    磁性材料均匀地涂覆在圆形的铝合金载体上就成为硬磁盘盘体,当磁头上的写线圈中通过一定方向的脉冲电流时,磁头铁芯内就产生一定方向的磁通。在磁头缝隙处则会产生很强的磁场并形成一个闭合回路,磁头下方硬磁盘盘体上一个很小区域被磁化形成一个磁化元(即记录单元)。若在磁头的写线圈中通过相反方向的脉冲电流,该磁化元则向相反方向磁化。如果某一个方向的脉冲电流将磁头下方硬磁盘的极小区域磁化为信息"1"的话(写入"1"),那么相反方向的脉冲电流就会将磁头下方硬磁盘的极小区域磁化为信息"0"(写入"0")。也就是说,硬盘中的"0"和"1",是用盘体上磁化元的不同磁化方向来表示的。

     

    本文讲内存的实现,从底层的二极管到内存的电路结构,本章逻辑线路为:电路-->二极管-->逻辑门-->组合逻辑单元j和存储单元-->内存

    我们知道计算机本质是在做0和1的二进制运算,那么内存从抽象意义上看也是保存着0和1,那么问题是怎么保存这些0和1呢?下面就说说内存的硬件实现哈。

    电路

    先从一个简单电路看起,

    image

    二极管

    然而我们要控制二进制,在计算机里我们用两种互补的二极管(CMOS即n-MOS管和p-MOS管)实现这个开关,这两种原理如下。

    image

    n-MOS管,栅极端(Gate)通电后,则电路联通,栅极断电则电路断开

    image

    p-MOS管反过来,栅极端(Gate)通电后,则电路断开,栅极断电则电路联通

    提示:小圆圈表示“非”,即取反的意思,若输入为1,流经小圆圈后则变为0

    逻辑门

    通过这些二极管的组合,我们可以实现计算机里的“与”、“或”、“非”逻辑电路。

    非门(NOT):

    image

    对应真值表:

    InOut
    01
    10

    或门(OR):

    image

    真值表:

    ABC
    000
    011
    101
    111

    与门(AND):

    image

     

    真值表:

    ABC
    000
    010
    100
    111

    既然知道逻辑门的二极管实现后则可以用符号替代这复杂的底层实现。

    image

    看完了逻辑门,紧接着看计算机内的逻辑单元。逻辑单元可以分为两类:

    1. 一类不可存储信息的(组合逻辑单元)
    2. 另一类可存储信息(存储单元)。我们分别介绍和内存相关的几个结构。

    组合逻辑单元

    不可储存信息的结构:用于计算或控制二进制

    1. 译码器:依据输入端的二进制,在输出端选中某一条电路

    image

    如图,如果A=0,B=0,则选中最上面的那条线

    1. 多路复用器:根据控制信号,只选择输入端的某根电路,把这根线输出到输出端

    image

    如图,若S1=0,S2=0,则A线路被选中,A的值即是输出值。

    存储单元

    可存储信息的结构:可用于保存二进制

    1. 门控D锁存器

       

      image

    • WE=0时(不可读写),S和R必为1,则电路稳定,out端可保持原来的值
    • WE=1时(可读写),则根据D的值,out端变为对应的值。然后恢复WE=0则保存起来
    1. 寄存器:
      一个门控D锁存器只能保存一个bit,则组合起来就能保存n个bit,这就是寄存器

    image

    介绍完这些组成结构后,我们终于可以讲解内存啦!

    内存

    先介绍两个概念:

    1. 寻址空间:即能保存多少个内存地址,我们通常意义上的4G内存,就表示计算机能保存2的32次方个地址!能保存这么多地址,也就能找到这些地址上的二进制信息

    2. 寻址能力:每个地址里具体存多少个bit,由于历史原因,绝大部分计算机都是8bit的寻址能力。

    那么我们来看一个超简单的内存哈。这个内存是2的2次方的寻址空间,即只能查找4个地址。寻址能力是3个bit,即每个地址只能存3个bit。

    image

    如图

    1. 内存的寻址由一个2个输入的译码器实现。译码器根据A1和A2的输入,选中对应的一条线,即找到地址对应的存储空间。
    2. 内存存储信息的能力具体实现是由门控D锁存器保存bit信息。
    3. 读取内存的输出由多路复用器实现。根据寻址时译码器选中的某一个线路,每一列的多路复用器只能输出那个线路的对应的那个门控D锁存器保存的bit。则最终的三个bit都是由同一个线路对应的三个门控D锁存器的输出。

    这就是内存的实现原理了哈。



     

    展开全文
  • XC7K325T 4片DDR内存读写测试(含教程和FPGA工程),实现的4片64BIT,DDR3用MIG读写数据的测试,DDR3稳定运行于800M(1600M 数据时钟),附件有FPGA工程,操作说明,参考原理
  • 纯c++源代码,不是.sys,不懂编程的就别下载了,会浪费你的积分的。 可以修改CPUID和硬盘ID,里面集成了各种钩子处理、隐藏驱动、伪装、PatchGuard、文件保护、窗口保护、拦截数据包、绕过反调试、等等......
  • 磁盘 内存 读取数据原理

    千次阅读 2019-11-26 09:02:20
    当程序要读取的数据时传入内存地址(行地址+列地址),如果数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,通过柱面号,磁头号,扇区号定位磁盘位置,找到数据的起始位置并向后连续读取一页...
  • 内存实现功能:大家都知道安卓实现找坐标要识别数据,要制作字库找图找色,可能要很多尝试调试,还要加各种算法等一些麻烦的东西,如果用内存反而简单的,可能你在几分钟之内就能够把坐标、地图名字、...
  • windows内存读写监视

    热门讨论 2012-02-26 13:30:48
    windows内存读写监视 windows内存读写监视
  • 主要介绍了Go语言共享内存读写方法,实例分析了共享内存的原理与读写技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 文档是本科时候的一个课程设计,里面详细介绍了EM4100 ID卡的读写原理以及电路设计,文末附了PCB图以及原理电路图,并且有示波器波形仿真分析。
  • 可以监视指定进程的内存写操作。。方便对其它软件的分析,主要是HOOK了写内存函数。。
  • 跨进程root读写内存原理(JNIRoot方案)

    千次阅读 多人点赞 2021-03-04 11:02:17
    关于跨进程读写应用内存的文章和案例我翻遍了csdn,简书,github,gitee,发现都不多且不详细,于是决定发布一篇博文来讲解一下原理。 进入话题 此技术核心用到了java反射技术和AIDL(IPC)管道通信技术。 大体逻辑 ...
  • 易语言 DLL劫持生成 ...更新来了!!! 更新的比较仓促,祝大家新年快乐。...如果不加载winmm.dll 可能是你系统默认加载的System32目录下的winmm.dll了 自行解决吧 只要成功劫持了 受驱动保护的进程同样可以读写内存
  • kudu 的基本架构与存储结构 1. 基本架构 TMaster and TServer TMaster 主要用来管理元数据,即tablet 和 表的...tablet 负责这一张表的某块内容的读写,接受其他tablet leader 传来的同步信息,至于什么是tablet,...
  • 计算机内存读取写入原理是什么

    千次阅读 2013-04-19 12:32:24
    计算机内存读取写入原理是什么? 通常我们所熟悉的计算机内存条,外观是一个长方形的,上面有的黑色小正方形就是内存颗粒,还有一些电子原件,内存的工作原理分4部分,请楼主耐心看完: 内存...
  • 手游作弊-内存读写实例

    千次阅读 多人点赞 2021-01-04 00:31:04
    关于手游作弊的博客我鸽的有点久了哈哈,这篇文章就和大家讲解下在内存中数据的存储格式,如何读取和修改
  • HDFS的读写原理

    千次阅读 2019-02-27 14:14:03
    然后将block按键值对存储在HDFS上,并将键值对的映射存到内存中。如果小文件太多,那内存的负担会很重。 如上图所示,HDFS也是按照Master和Slave的结构。分 NameNode 、 SecondaryNameNode 、 DataNode 这几个...
  • XC7K325T基于FDMA内存读写测试设计(含视频和FPGA工程),有操作教程,FPGA源码(VIVADO2017.4打开),参考原理图,资料总共213MB。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 203,931
精华内容 81,572
关键字:

内存读写原理