PX-15-变量内存和cpu原理
1.变量和内存原理
内存是运行程序的场所,磁盘时存放数据的。运行程序实际是将文件从硬盘拖到内存里来。
游戏外挂为什么能实现更改数据?
因为,计算机中,指令代码、数据都存储于内存中。变量也需要存储在内存中。只要突破权限控制就可以对代码进行任意的更改!
2.调试器
cpu 和 内存 对变量如何发挥作用的?
3.查看变量在内存中断点查看
#include<stdio.h> void main1() { int a = 10; printf("%p", &a);//查看a的内存地址 printf("\n%d", a); getchar(); }
内存的原理: 同一个时间,内存空间里只能保存一份值,新值冲掉了原来的旧值。每个内存单元都有编号,这些是内存的地址。
变量变化的原理:在内存中存放不同的数据,当内存发生变化的时候,变量也会发生变化。
4.变量的内存机制

编译器的处理过程:
(1)明确存储的类型,然后处理变量名
(2)变量表

例如计算,1+2=3,a=1,b=2,c=3,C =a+b
当引用了a,b,c会创建变量表
变量表的作用: 管理所有的变量
void main2() { int a, b, c; //变量表,管理所有的变量
//会自动生成一张变量表
//没有声明d //不能引用未曾声明的变量 printf("\n%d", d); getchar(); }
//执行后会报错 ,为声明的标识符

(3)c / c++ 不会默认对变量进行初始化

java c#会默认声明变量时候对变量进行初始化
(4)
void main4() { int a = 3; //赋值,只能给变量赋值,变量在内存 //a + 1 = 4; a+1属于寄存器, int b = 0; printf("%p", &b); b = a + 1; b = a + 2; getchar(); }

上图分析出 a+1 不在内存中实现而是在寄存器中!
- a+1=b 为什么是不对的?
a+1 计算的过程发生在寄存器中!寄存器不能被赋值!
赋值只能给变量,变量在内存中;计算不发生在内存中;
计算并不在内存中进行因此无法赋值,计算发生在寄存器中。EAX中;
结论: 对数据进行的所有操作都是通过cpu ,如果不通过cpu 内存是不能直接赋值的;
只有变量可以进行赋值操作,变量必须要在内存里。
(5)用汇编语言演示变量在内存中被赋值和被计算的过程
void main() { int a; printf("%p", &a); //变量赋值,都是CPU的寄存器完成 //a = 10; //代码区的常量符号表10,100 //printf("%p", &10);
_asm { mov eax ,10
mov a,eax } printf("\na=%d", a); _asm { mov eax,a add eax,5 mov a,eax } printf("\na=%d", a); getchar(); }

变量赋值,都是CPU的寄存器完成
(6)a=10
10在寄存器里产生。首先从代码区的符号表中读取出来 然后再寄存器中产生;然后控制器将寄存器中的值赋值给,cpu分配给a的这块内存上,这样 a的值发生了变化
//printf("%p", &10);
取地址取得是内存地址 10 在寄存器里产生
12345678910 ---等整数 cpu 要计算出二进制才能操作
10是编译器有一个地方存储了一个10 通过cpu提取数据 将他存放在寄存器里面 在进行赋值
10---存在 --代码区的常量符号表---里 用到什么就存了进去编译进去 //代码区 内存4区 只读不写!
首先从代码区的符号表中读取出来 然后再寄存器中产生 然后再将值赋值给内存的变量 所以这片内存发生变化
10 要进行赋值要通过cpu 将寄存器的值赋值给内存,内存不能直接赋值。
2.格式控制符“%p”
格式控制符“%p”中的p是pointer(指针)的缩写。指针的值是语言实现(编译程序)相关的,
但几乎所有实现中,指针的值都是一个表示地址空间中某个存储器单元的整数。
printf函数族中对于%p一般以十六进制整数方式输出指针的值,附加前缀0x。
示例: int i = 1; printf("%p",&i);
相当于 int i = 1; printf("0x%x",&i); 对于32位的指针,输出一般会是类似0xf0001234之类的结果。 %p存在的理由除了附加前缀输出的便利性以外,指针的大小是不确定的,由实现决定。根据地址空间的大小,一般有16位、32位、64位的指针。
尽管目前32位平台上的指针一般全是32位的,但旧的一些平台上可能有多种长度的指针(例如非标准的near、far、huge修饰的pointer)混用,
无法用%x、%lx、%hx、%llx(对应int、long、short、long long)中的任意一种保证能输出所有类型的指针。
-------------------------------------------------------------------------------------------------------------------
3.变量的内存机制
计算机中,指令代码、数据都存储于内存中。
变量之所以可以变化,就是这个存储空间可以存储不同的数值。存储空间里的值变化,则变量对应的值也变化。
同一个时间,内存空间里只能保存一份值,新值冲掉了原来的旧值。每个内存单元都有编号,这些是内存的地址。
4.变量表的概念

void main4() { int a = 3; //赋值,只能给变量赋值,变量在内存 //a + 1 = 4; a+1属于寄存器, int b = 0; printf("%p", &b); b = a + 1; b = a + 2; getchar(); }
6.在c语言中嵌入汇编语言的方式
//变量赋值,都是CPU的寄存器完成
_asm
{
mov eax ,10
mov a,eax
}
//相当于 a=10
7.
// a+ = 5 的实现过程
_asm { mov eax,a add eax,5 mov a,eax } printf("\na=%d", a); getchar(); }
8. a=10
10在寄存器里产生。
//printf("%p", &10);
取地址取得是内存地址 10 在寄存器里产生
12345678910 ---等整数 cpu 要计算出二进制才能操作
10是编译器有一个地方存储了一个10 通过cpu提取数据 将他存放在寄存器里面 在进行赋值
10---存在 --代码区的常量符号表---里 用到什么就存了进去编译进去
首先从代码区的符号表中读取出来 然后再寄存器中产生 然后再将值赋值给内存的变量 所以这片内存发生变化
//代码区 内存4区 只读不写!
---
10 不在内存里 ,所以 &10 是不对的; 是不可以 原因:变量可以取地址在内存中 ,10在寄存器中产生的, 无法在寄存器中取地址
10 -- 编译器有一个地方存储了10
//变量赋值,都是CPU的寄存器完成
//a = 10;
//代码区的常量符号表10,100
//printf("%p", &10);
程序示例代码:
#include<stdio.h>
void main1()
{
int a = 10;
printf("%p", &a);//查看a的内存地址
printf("\n%d", a);
getchar();
}
void main2()
{
int a, b, c; //变量表,管理所有的变量
//不能引用未曾声明的变量
//printf("\n%d", d);
getchar();
}
void main3()
{
int a = 1;
int b = 2;
int c;
printf("a=%p,b=%p,c=%p", &a, &b, &c);
c = a + b;
getchar();
}
void main()
{
int a;
printf("%p", &a);
//变量赋值,都是CPU的寄存器完成
//a = 10; //代码区的常量符号表10,100
//printf("%p", &10);
_asm
{
mov eax ,10
mov a,eax
}
printf("\na=%d", a);
_asm
{
mov eax,a
add eax,5
mov a,eax
}
printf("\na=%d", a);
getchar();
}
//代码区 内存4区 只读不写!

浙公网安备 33010602011771号