‘壹’ arm-linux程序的链接地址和原先地址
连接器脚本xxx.lds文件中指定的地址,就是链接地址,程序运行时必须位于它的链接地址处,汇编文件中的各个标号或者c文件中的各个函数名(函数的入口地址)对应的链接地址就是由链接脚本中的起始链接地址和各个目标文件(.s或.c文件编译但还为链接的文件)的排放顺序有关。这些链接地址可以通过查看可执行文件的反汇编文件即xxx.dis文件来获得.
如果你不使用全局变量或者静态变量,访问这些变量时要使用到链接地址,重定位完成之前不能使用这些类型的变量,adr、b和bl指令都是属于相对跳转指令,即在当前pc值的基础上加减一个偏移值,跳转去执行。如果只使用adr、b或者bl指令,并且不访问全局变量或者静态变量,这类代码被称为“位置无关码”,即代码的存储位置可以不在其链接地址处。如果当使用全局跳转指令ldr时就只能使用链接地址了,如ldr pc,_reset。程序运行时,pc指针的内容是不区分原本地址(存储地址)或链接地址的,只要是”位置无关码“,存储地址可以与链接地址不同,不是位置无关码就要使用到链接地址,即存储地址与链接地址必须相同。即使用之前必须完成代码的重定位。
ps:望采纳!
‘贰’ c语言程序加载到内存时,程序内各段之间的地址是连续的吗
不联续吧,编译器会按一定组织,加载到内存时以一定方式映射,有本《加密解密内幕》的书讲这个很好
‘叁’ C语言的&运算符取的是逻辑地址还是物理地址 每次重新编译运行后 输出变量的地址值都一样 怎么理解
您需要了解一下操作系统的虚拟内存机制。
操作系统会为新建立的每一个进程开辟一个独立却完整的地址空间(32位机器是4GB),其中除了一部分地址要交给操作系统的内核或用于某些特殊功用,程序可以自由地使用这些内存,就好像每个进程可以独自使用一台4GB内存的机器一样。但是要注意这是由操作系统虚拟出来的,系统的内存管理器要负责把这些虚拟的内存映射到真实的物理内存中。系统往往同时运行很多进程,要把真实的内存给每个进程都分配4GB当然不可能,所以系统往往还要借用硬盘来存放物理内存存不下的内容,协助虚拟内存的实现。实际的物理内存的状况是:零散无规律地分布着各个进程的内存页面。
当一个新进程启动时,操作系统首先为该进程创建虚拟内存空间,然后把程序的代码段和一部分数据放在固定的虚拟内存地址上。你说的那个变量A就是被包含这部分数据中,每次启动程序都可以看到它在一个固定的地址上,但是这个地址是在虚拟内存中的,实际它所对应的真实物理内存的地址是未知的,只有管理内存的系统内核知道。
当然,还有一部分数据在你的虚拟内存空间的地址也是未知的,这就是堆,堆允许程序在运行过程中动态分配和释放内存(其他的内存分配方式在程序启动时就在固定位置分配,不能改变),堆的分配和释放由C运行时库和操作系统协同管理,分配的内存地址是随机的。你说的那个变量A不是堆中的。
你说的逻辑地址就是在虚拟内存中的地址,物理地址就是在真实的物理内存中的地址。
对于以上有不懂的概念名词可网络查资料。
‘肆’ C程序:关于编译的问题。。。(回答好的可继续加分)
1、是,obj文件里面有段信息
2、没有,堆是运行的时候由运行库给你分配的(windows下vc运行库其实用的是系统提供的堆),栈式运行的时候系统给你分配的,编译后的obj里面甚至连栈段有多大这样的信息都没有(这是链接的时候加上去的)
全局变量的逻辑地址是不变的这说法在没开启动态基地址的时候是正确的,每次exe加载到内存中以后,同一个全局变量都在同一个位置。不过windows下开启动态基地址之后每次exe都可能被加载到不同的地址上,这个时候全局变量的内存地址就会变化了。
‘伍’ 请问程序在编译和链接的时候,逻辑地址是否是连续的请高手解答。谢谢。
函数内部是连续的吧,因为一起分配的栈; 不同函数的栈可能就不连续了啊
‘陆’ 程序变量每次运行,申请的内存地址一样么
我们所看到的这个地址并不是真正物理地址的值,每个程序在windows开始运行都需要开辟空间,这个空间根据当前系统中运行的程序的多少和先后顺序都会有所不同,我们看到的这个变量地址其实是相对于本程序进程的起始地址的偏移量。举个例子来说,你写了个a.exe程序,这一次运行a.exe程序系统分配给他的起始内存空间地址是4012ff00,那么这个变量在开辟空间的时候,可能之前已经定义了一些变量或者其它结构占用了7c的空间,则这个变量地址为4012ff7c,偏移地址为0012ff7c;关掉这个程序,再开它,则可能进程地址变为了5012ff00,那么这个变量的物理地址就为5012ff00,偏移地址仍旧为0012ff7c。
但是也不是说这个偏移地址是一成不变的,这涉及到这个变量的开辟时是不是总是固定在一个顺序上,例如
我写个函数像这样:
void
aa(int
m)
{
if(m>5)
{
int
x=2;int
y=3;int
z=0;z=x+z;
}
else
{
int
z=2;int
x=3;int
y=0;y=x+z;
}
}
那么显然x这个变量的开辟时间点取决于变量m的大小,则开辟的先后也决定了x这个变量的地址,所以这些变量是动态变化的,如果涉及到结构和类的成员变量,还需要考虑这个结构或类对象的创建次序,这需要涉及到一些底层的思想
‘柒’ 4、同一个程序在不同编译器(比如VC或TC)下第一个变量的地址是否相同,均为ox12ff7c如果相同,为什么
不一定形同 因为C语言在编译程序时 通常会根据你的内存来进行选择 并进行优化 这和你的硬件还有关
‘捌’ 计算机内存是动态分配的,程序每次运行的物理地址都不一样,但偏移地址是不变的。偏移地址是谁分配的
一般程序的偏移地址,相对于其实地址 比较固定吧,没弄成话和程序编译相关。之后在根据实际操作系统分配的内存空间进行偏移。,地址冲突,是靠操作系统控制,4G地址空间,程序使用的是虚拟地址,进过操作系统翻译后才是实际地址。一般程序是通过操作系统中介才能放到内存数据。不能直接访问。
‘玖’ 为什么C语言变量的地址每一次运行都是一样的,在360隔离沙箱里运行也是一样的
变量地址是由编译器决定的
360隔离沙箱是不让程序写入磁盘,不是不让程序加载内存
‘拾’ 我用visual studio 2019,为什么每次输出相同变量的地址都不一样的
建议先研究一下数据结构,在内存中每次程序声明变量时,都会顺序从地址空间中找一块大小足够的空间,不同时间编译,因为系统各种后台等占用的内存有变化,所以地址会不同