编译器连接地址是内存地址
Ⅰ 鍦板潃璇戠爜鍣ㄥ湪浠涔堜綅缃
鍦板潃璇戠爜鍣ㄥ湪鍐呭瓨褰扑腑銆
鍦板潃璇戠爜鍣锛氩氨鏄鎶婅緭鍏ョ殑浜岃繘鍒舵暟鍦板潃锛屾寚钖戠浉搴旂殑鐗╃悊绌洪棿銆傚湴鍧璇戠爜鍣ㄦ槸鍦ㄥ唴瀛桦唴閮ㄧ殑锛屽唴瀛橀櫎浜嗗瓨鍌ㄥ崟鍏冨栵纴杩桦寘𨰾锛氲诲啓鐢佃矾銆佸湴鍧璇戠爜鍣ㄣ
鍦板潃璇戠爜鍣ㄦ牴鎹杈揿叆鍦板潃阃夋嫨镆愭浔杈揿嚭锛埚瓧绾匡级锛屽啀鐢卞畠椹卞姩璇ヤ綅绾匡纴浠ヤ究璇诲嚭瀛楃嚎涓婂悇鍗曞厓瀛桦偍镄勪唬镰併
Ⅱ 缂栬疟杩囩▼涓鍐呭瓨镄勫垎閰崭笌閲婃斁
缂栬疟杩囩▼涓锛屽唴瀛樼殑鍒嗛厤涓庨喷鏀炬槸涓涓闱炲父閲嶈佺殑鐜鑺伞傛爤绌洪棿鍜屽爢绌洪棿鏄鍐呭瓨绠$悊涓镄勪袱涓閲嶈佹傚康锛屽畠浠钖勮嚜链夌潃镫鐗圭殑鐗圭偣鍜岀敤阃斻傛湰鏂囧皢娣卞叆鎺㈣ㄦ爤绌洪棿鍜屽爢绌洪棿镄勫尯鍒锛屼互鍙婂畠浠鍦ㄥ唴瀛樼$悊涓镄勪綔鐢ㄣ
📚镙堢┖闂村拰鍫嗙┖闂寸殑鍖哄埆
镙堢┖闂存槸鐢辨搷浣灭郴缁(缂栬疟鍣)镊锷ㄧ$悊锛屽畠涓哄彉閲忓拰鍑芥暟鎻愪緵涓存椂镄勫瓨鍌ㄧ┖闂达纴骞跺湪杩愯屾椂镓ц屽弬鏁颁紶阃掋傝屽爢绌洪棿鍒欐槸鍦ㄧ▼搴忚繍琛屾椂锷ㄦ佸垎閰岖殑锛屽ぇ灏忓彲镙规嵁闇姹傝皟鏁淬傜浉姣斾箣涓嬶纴鍫嗗唴瀛桦垎閰岖敱C/c++鍑芥暟搴撹礋璐o纴鍏锋湁镟村ぇ镄勭伒娲绘у拰鏂逛究镐с
🚀鍫嗗唴瀛桦垎閰岖殑鏁堢巼闂棰
鍫嗗唴瀛桦垎閰岖敱C/c++鍑芥暟搴撹礋璐o纴鍏锋湁镟村ぇ镄勭伒娲绘у拰鏂逛究镐с备絾鐢变簬娑夊强锷ㄦ佸垎閰嶏纴鍏舵晥鐜囧彲鑳藉弹鍒板奖鍝嶃傜▼搴忓憳闇瑕佹敞镒忓湪浣跨敤鍫嗗唴瀛樻椂锛屽敖鍙鑳藉噺灏戝唴瀛桦垎閰岖殑娆℃暟锛屼互鎻愰珮绋嫔簭镄勬晥鐜囥
🔗镙堢┖闂村拰鍫嗙┖闂寸殑镵旂郴
鍦ㄥ唴瀛樼$悊鏂归溃锛屽爢阃氩父鐢ㄤ簬淇濆瓨鏂板垱寤虹殑瀵硅薄鍜屾暟缁勶纴骞剁敱铏氭嫙链虹殑镊锷ㄥ瀮鍦炬敹闆嗗櫒璐熻矗绠$悊銆傚綋鍦ㄥ爢涓鍒涘缓涓涓鏁扮粍鎴栧硅薄镞讹纴镙堜腑鍙浠ヨ剧疆涓涓寮旷敤鍙橀噺锛屼娇鍏跺肩瓑浜庤ユ暟缁勬垨瀵硅薄鍦ㄥ爢涓镄勫湴鍧銆傝繖镙凤纴鎴戜滑鍙浠ラ氲繃杩欎釜寮旷敤𨱒ヨ块梾鍫嗕腑镄勬暟鎹銆
💡鍫嗗唴瀛樼殑绠$悊
绋嫔簭锻橀氩父璐熻矗绠$悊鍫嗗唴瀛樼殑鍒嗛厤銆傞渶瑕佹敞镒忕殑鏄锛屽傛灉鏁扮粍鎴栧硅薄娌℃湁寮旷敤鍙橀噺鎸囧悜瀹冿纴鍗充娇瀹冨湪鍫嗕腑鍒嗛厤浜嗗唴瀛桡纴涔熶细阃犳垚鍐呭瓨娴璐癸纴锲犱负鍨冨溇鏀堕泦鍣ㄦ棤娉曞湪涓岖‘瀹氱殑镞堕棿閲婃斁杩欓儴鍒嗗唴瀛樸
Ⅲ c语言竟是如何调用硬件
大家都知道我们可以使用C语言写一段程序来控制硬件工作,但你知道其工作原理吗?以下仅供参考!
c语言在实际运行中,都是以汇编指令的方式运行的,由编译器把C语言编译成汇编指令,CPU直接执行汇编指令。
所以这个问题就变成,汇编指令是如何操作硬件的?
如果把硬件平台限制在x86环境下,那么汇编指令操作硬件基本上只有两种方式:
方式一:
通过向内存空间写数据。硬件会把硬件上的各种寄存器(外行可以理解为访问硬件的接口或者操作硬件的工具)映射到某一块内存地址空间上,之后只要用汇编指令,甚至C语言去读写这一段内存地址空间(并非真正操作物理内存),就可以达到操作硬件的目的了。
如果题主还有WindowsXP环境(虚拟机也可以),就可以用汇编指令直接操作显存:
MOV AX,B800
MOV ES,AX
XOR DI,DI
MOV CX,0800
MOV AX,5555
REPZ STOSB
硬件的各种寄存器会被映射到某一块物理内存中,这种方式称为MMIO,在Windows的设备管理器里,右键点设备,看属性-》资源里,不少硬件设备都有“内存范围”的参数,这里的内存范围就表示这个硬件的资源可以通过访问这一段内存来控制它。
方式二:
x86汇编中,还有两个特殊的指令是IN和OUT,这是x86平台上独有的,上面图里的I/O范围,就是用IN/OUT这两个指令来访问和控制的。
以上两种访问硬件的方式,第一种是可以用C语言实现的,上面一段汇编,本质上类似于C语言代码:
char ptr = 0xB8000;
int i;
for (i = 0; i 《0x800; i++)
{ptr + i = 0x55;
}
第二种IN/OUT方式没有直接的C语言语法对应,需要自己封装汇编。
那么为什么平时很难用C语言操作硬件呢?这是因为平时写的代码大多数都在保护模式下,保护模式下,直接访问物理地址会受到限制,C语言操作的地址都是虚地址。
对于Windows来说,要访问物理地址,需要工作在内核模式,也就是的写驱动才行。
而在显存方面,首先,题主要先明白物理地址和虚拟地址的概念。
原来的8086cpu设计的时候,地址空间有一块区域(640K-1M)之间,有一块作为显存使用
这里你说的预留的地址,是指物理地址,这一段地址的准确范围是000A0000-000BFFFF,不管是32位还是64位CPU,这一段物理内存地址一直都保留给显存使用,不区分32位还是64位,也不区分保护模式还是实模式。
可见这一段内存至今仍然是留给显卡使用的。
那么现在为什么不能直接用这段内存了?
因为现在的软件都运行在保护模式下,访问的地址都是虚拟地址,而并非物理地址,包括你使用cmd命令打开的环境,都是虚拟地址,虽然32位XP里能用debug命令向000B8000上写数据并能显示在cmd的界面里,但本质上,这都是虚拟出来的。
如果要想用这段显存怎么办?
自己写一个简易的操作系统,不启动显卡的各种图形加速功能,CPU进入保护模式后在GDT里映射一个4G的数据段,与物理地址一致,那么向000B8000上写数据,就会像过去DOS一样显示在屏幕上,所以保护模式下也可以访问这一段内存。所以,保护模式下,也可以用它。
显卡那么多显存是怎么映射的?
有很多内存地址被映射给显存了,就是通过这种映射关系,把一些物理地址留给显存,使得CPU能像访问内存一样访问显存资源。
当然,实际情况是,2G显存未必完全映射,而是只映射一部分地址,显卡有一些开放的寄存器能够控制哪部分显存映射过来,这样就能使得CPU在使用比较少的物理地址范围的情况下,访问全部的显存。
还有一个很有意思的事情:在虚拟机里,找到映射的高地址部分的第一块内存区域,写一个能直接访问物理地址的程序(比如一个驱动),去读这一块内存,然后写到文件里,再用屏幕截图,也写到文件里,会发现截图的内容和显存里读出来的内容基本上是一样的。
网友awayisblue
要回答你的问题,我们需要要知道:
硬件是一种什么样的存在
什么是驱动。
C语言怎么操作硬件
我就不严格去定义这些概念了,我就以一个例子来通俗地讲解一下吧。
首先讲硬件:
先介绍一款单片机芯片STM8。
这款芯片里面有cpu, 内存,寄存器(先不要觉得看到新名词压力大,继续往下看)等等,相当于我们的电脑了,但还要外接其它硬件。
这里你需要知道的概念是:
芯片的引脚跟寄存器是相对应的,寄存器是8位的内存单元(对,存在于内存上面),当你往这个内存单元里面写入数据时,芯片的引脚的电压会发生变化,比如说我写入的是01100001,则芯片上与之对应的8个引脚的电压状态(分为高电平与低电平两种)会输出:低高高低低低低高。
cpu可以执行代码指令,指令可以操作内存。
结论:所以从上面两点可以我们可以知道,cpu可以执行指令,使芯片的引脚电平(电压)发生变化。
关于这款显示器,我们需要知道的是:
它是有引脚的,这些引脚可以跟到前面介绍的那款单片机芯片的引脚相连。
该显示器有自带的内存,用于存储要显示的字符,显示器从该内存里面读取字符来来显示。
单片机芯片与该显示器相连后,可以通过引脚往该显示器的内存里写数据(通过多个引脚电平的高低不同来代表不同的数据,比如说:低高高低低低低高 代表01100001,这个数据写在显示器的.内存里面,被显示器所显示,当然,会根据ASCII来显示数字对应的字符,01100001对应的字符是‘a’),除了接收数据的引脚外,还有控制显示器的引脚(这个我们会在驱动那里介绍,继续往下看)。
结论:单片机芯片与显示器相连,可以通过引脚输出的电平来控制显示器的字符显示。
那么,综合上面,也就是说,单片机芯片cpu可以通过执行指令来控制显示器的字符显示。
而这里,题主所说的硬件,指的就是这个显示器了。
接下来讲驱动:
那么,什么是驱动呢?驱动无非就是硬件跟软件的中间层,但我们不纠结这种关系,直接来看一下,对于我们这个例子,驱动指的是什么。首先我们要知道:
显示器支持很多种操作,比如说清除显示,光标移动,读取数据,写数据等等。
这些操作数据引脚和控制引脚来实现。
引脚可以通过单片机芯片来控制。
结论:我们可以通过在单片机芯片里面写显示器的“驱动”程序来屏蔽掉硬件(显示器硬件)层。
于是这里驱动程序,指的是显示器所支持操作的程序表示。比如说清除显示,我们可以编写一个clear()函数,光标移动,我们编写一个move_cursor()函数,读取数据和写数据分别为read()和write(),然后分别实现就可以了(通过向寄存器里写数据的形式,进而控制引脚的电平变化,再而控制显示器,这个过程前面已有介绍)。这些函数就是驱动程序了。为什么上面说驱动程序可以屏蔽掉硬件呢?因为程序员可以使用前面的驱动程序来直接操作显示器(硬件),而不用知道太多关于硬件的事情,而一般的驱动程序也可以由厂家来提供。
再说明一点:一般这些驱动程序可以用汇编写(出于运行效率的考虑),也可以用C语言来编写的,比如说我上面的例子,就可以直接用C语言来编写。当然C语言内联汇编的形式也可以。
最后讲C语言怎么操作硬件:
相信到这里,C语言是怎么操作硬件的已经比较明白了。
这里总结一下:
C语言由CPU运行(实际上是先编译成机器码存在芯片里面然后执行),可以去操作内存。
内存里有一段是跟寄存器相对应的,而寄存器是跟芯片的引脚相对应的,于是操作该段内存就能控制芯片引脚的电压变化。
硬件(比如说显示器)有引脚(或者说排线,这些也是一样的东西),这些引脚跟芯片的引脚相连可以接受芯片的控制。
可以把对某个硬件的操作做成一系列操作函数,这些操作函数就是驱动程序了。
于是我们的C语言只要去调用这个驱动程序就可以直接操作硬件了。(当然驱动程序也可以由C语言来编写,所以C语言操作硬件并不一定要经过驱动程序)。
Ⅳ 高级语言源程序编译后产生的地址是逻辑地址还是物理地址
由于操作系统技术的发展,可重用二进制程序技术使用了内存重定位技术,所以从汇编的角度来看即不是逻辑地址也不是物理地址。而且这个概念有些不同,编译后产生的地址是相对地址,是相对于可执行头部位置的地址。而逻辑地址是指在指令系统内部使用的用来访问内存的一个逻辑表示,通常表现为相对于某个段基地址的偏移量。
当可执行程序被载入内存之后,才会有逻辑地址存在,此时可执行程序被如何加载于何处,地址为多少,由操作系统决定,此时cpu访问程序用的是逻辑地址。一个程序一旦被编译确定之后基本上变量初始化的顺序固定,资源分配位置也固定,设置有编译器使用预分配机制,然后采用相对地址引用。
注意:某些工具书也称二进制可执行文件内所有的相对地址范围是逻辑地址空间,相对地址就是逻辑地址。因为两者的访问方式相似,逻辑地址变换依赖cpu或者附加变换机构(硬件),而二进制程序地址空间变换需要操作系统插手管理。
反汇编分析中常常将二进制内部地址称为逻辑地址,因为反汇编器不能还原原来汇编代码的地址跳转空间特性,因此得到一个相对于二进制数据起点位置的相对地址,而和内存和物理存储都没有关系。
Ⅳ vs2010镆ョ湅鍐呭瓨鍦板潃镄勬柟娉
銆銆鍦ㄤ綘浣跨敤vs缂栫▼锛屾兂瑕佺敤镆ョ湅vs镄勫唴瀛桦湴鍧锛屽彲浠ュ湪璁剧疆闾i噷淇鏀癸纴璇︾粏𨱍呭喌浠ヤ笅鎴戜负澶у舵暣鐞嗗ソ浜呜祫鏂欙纴甯屾湜澶у跺枩娆銆
銆銆 vs2010镆ョ湅鍐呭瓨鍦板潃
銆銆1銆侀栧厛镓揿紑vs缂栬疟鍣锛屽垱寤哄ソ椤圭洰锛屽苟涓斿皢浠g爜鍐栾繘铡伙纴杩欓噷灏变笉璐翠唬镰佷简锛屼綘鍙浠ラ殢渚跨殑鍐欎釜锅氢釜娴嬭瘯銆
Ⅵ 在ARM汇编编程中如何指定某段程序的存储地址
在要指定代码的存储空间不是一件特别简单的事情,尤其是你想为某个或某几个函数指定具体的地址。
1,编译器只有在最终的Link阶段才会为代码和数据分配内存地址,因此指定代码段的地址一般是通过写一个link脚本来进行的。Link阶段时,编译器的Linker会读取你写的Link脚本,并且按照脚本的规定给代码分配地址。
2,根据ARM开发工具的不同,link脚本的语法和形式也有所不同。ARM MDK,ARM ADS,Eclips+GCC,Linux GCC, ARM Realview等开发工具都支持Link脚本。
如果你英文还可以,建议你直接找到开发工具的Help手册去研究。如果你英语实在不行,也可以把开发工具名称和你代码的具体情况告诉我,我帮你看看。