- 相關(guān)推薦
C語(yǔ)言竟是如何調用硬件
大家都知道我們可以使用C語(yǔ)言寫(xiě)一段程序來(lái)控制硬件工作,但你知道其工作原理嗎?以下僅供參考!
c語(yǔ)言在實(shí)際運行中,都是以匯編指令的方式運行的,由編譯器把C語(yǔ)言編譯成匯編指令,CPU直接執行匯編指令。
所以這個(gè)問(wèn)題就變成,匯編指令是如何操作硬件的?
如果把硬件平臺限制在x86環(huán)境下,那么匯編指令操作硬件基本上只有兩種方式:
方式一:
通過(guò)向內存空間寫(xiě)數據。硬件會(huì )把硬件上的各種寄存器(外行可以理解為訪(fǎng)問(wèn)硬件的接口或者操作硬件的工具)映射到某一塊內存地址空間上,之后只要用匯編指令,甚至C語(yǔ)言去讀寫(xiě)這一段內存地址空間(并非真正操作物理內存),就可以達到操作硬件的目的了。
如果題主還有WindowsXP環(huán)境(虛擬機也可以),就可以用匯編指令直接操作顯存:
MOV AX,B800
MOV ES,AX
XOR DI,DI
MOV CX,0800
MOV AX,5555
REPZ STOSB
硬件的各種寄存器會(huì )被映射到某一塊物理內存中,這種方式稱(chēng)為MMIO,在Windows的設備管理器里,右鍵點(diǎn)設備,看屬性-》資源里,不少硬件設備都有“內存范圍”的參數,這里的內存范圍就表示這個(gè)硬件的資源可以通過(guò)訪(fǎng)問(wèn)這一段內存來(lái)控制它。
方式二:
x86匯編中,還有兩個(gè)特殊的指令是IN和OUT,這是x86平臺上獨有的,上面圖里的I/O范圍,就是用IN/OUT這兩個(gè)指令來(lái)訪(fǎng)問(wèn)和控制的。
以上兩種訪(fǎng)問(wèn)硬件的方式,第一種是可以用C語(yǔ)言實(shí)現的,上面一段匯編,本質(zhì)上類(lèi)似于C語(yǔ)言代碼:
char ptr = 0xB8000;
int i;
for (i = 0; i 《0x800; i++)
{ptr + i = 0x55;
}
第二種IN/OUT方式?jīng)]有直接的C語(yǔ)言語(yǔ)法對應,需要自己封裝匯編。
那么為什么平時(shí)很難用C語(yǔ)言操作硬件呢?這是因為平時(shí)寫(xiě)的代碼大多數都在保護模式下,保護模式下,直接訪(fǎng)問(wèn)物理地址會(huì )受到限制,C語(yǔ)言操作的地址都是虛地址。
對于Windows來(lái)說(shuō),要訪(fǎng)問(wèn)物理地址,需要工作在內核模式,也就是的寫(xiě)驅動(dòng)才行。
而在顯存方面,首先,題主要先明白物理地址和虛擬地址的概念。
原來(lái)的8086cpu設計的時(shí)候,地址空間有一塊區域(640K-1M)之間,有一塊作為顯存使用
這里你說(shuō)的預留的地址,是指物理地址,這一段地址的準確范圍是000A0000-000BFFFF,不管是32位還是64位CPU,這一段物理內存地址一直都保留給顯存使用,不區分32位還是64位,也不區分保護模式還是實(shí)模式。
可見(jiàn)這一段內存至今仍然是留給顯卡使用的。
那么現在為什么不能直接用這段內存了?
因為現在的軟件都運行在保護模式下,訪(fǎng)問(wèn)的地址都是虛擬地址,而并非物理地址,包括你使用cmd命令打開(kāi)的環(huán)境,都是虛擬地址,雖然32位XP里能用debug命令向000B8000上寫(xiě)數據并能顯示在cmd的界面里,但本質(zhì)上,這都是虛擬出來(lái)的。
如果要想用這段顯存怎么辦?
自己寫(xiě)一個(gè)簡(jiǎn)易的操作系統,不啟動(dòng)顯卡的各種圖形加速功能,CPU進(jìn)入保護模式后在GDT里映射一個(gè)4G的數據段,與物理地址一致,那么向000B8000上寫(xiě)數據,就會(huì )像過(guò)去DOS一樣顯示在屏幕上,所以保護模式下也可以訪(fǎng)問(wèn)這一段內存。所以,保護模式下,也可以用它。
顯卡那么多顯存是怎么映射的?
有很多內存地址被映射給顯存了,就是通過(guò)這種映射關(guān)系,把一些物理地址留給顯存,使得CPU能像訪(fǎng)問(wèn)內存一樣訪(fǎng)問(wèn)顯存資源。
當然,實(shí)際情況是,2G顯存未必完全映射,而是只映射一部分地址,顯卡有一些開(kāi)放的寄存器能夠控制哪部分顯存映射過(guò)來(lái),這樣就能使得CPU在使用比較少的物理地址范圍的情況下,訪(fǎng)問(wèn)全部的顯存。
還有一個(gè)很有意思的事情:在虛擬機里,找到映射的高地址部分的第一塊內存區域,寫(xiě)一個(gè)能直接訪(fǎng)問(wèn)物理地址的程序(比如一個(gè)驅動(dòng)),去讀這一塊內存,然后寫(xiě)到文件里,再用屏幕截圖,也寫(xiě)到文件里,會(huì )發(fā)現截圖的內容和顯存里讀出來(lái)的內容基本上是一樣的。
網(wǎng)友awayisblue
要回答你的問(wèn)題,我們需要要知道:
硬件是一種什么樣的存在
什么是驅動(dòng)。
C語(yǔ)言怎么操作硬件
我就不嚴格去定義這些概念了,我就以一個(gè)例子來(lái)通俗地講解一下吧。
首先講硬件:
先介紹一款單片機芯片STM8。
這款芯片里面有cpu, 內存,寄存器(先不要覺(jué)得看到新名詞壓力大,繼續往下看)等等,相當于我們的電腦了,但還要外接其它硬件。
這里你需要知道的概念是:
芯片的引腳跟寄存器是相對應的,寄存器是8位的內存單元(對,存在于內存上面),當你往這個(gè)內存單元里面寫(xiě)入數據時(shí),芯片的引腳的電壓會(huì )發(fā)生變化,比如說(shuō)我寫(xiě)入的是01100001,則芯片上與之對應的8個(gè)引腳的電壓狀態(tài)(分為高電平與低電平兩種)會(huì )輸出:低高高低低低低高。
cpu可以執行代碼指令,指令可以操作內存。
結論:所以從上面兩點(diǎn)可以我們可以知道,cpu可以執行指令,使芯片的引腳電平(電壓)發(fā)生變化。
關(guān)于這款顯示器,我們需要知道的是:
它是有引腳的,這些引腳可以跟到前面介紹的那款單片機芯片的引腳相連。
該顯示器有自帶的內存,用于存儲要顯示的字符,顯示器從該內存里面讀取字符來(lái)來(lái)顯示。
單片機芯片與該顯示器相連后,可以通過(guò)引腳往該顯示器的內存里寫(xiě)數據(通過(guò)多個(gè)引腳電平的高低不同來(lái)代表不同的數據,比如說(shuō):低高高低低低低高 代表01100001,這個(gè)數據寫(xiě)在顯示器的內存里面,被顯示器所顯示,當然,會(huì )根據ASCII來(lái)顯示數字對應的字符,01100001對應的字符是‘a(chǎn)’),除了接收數據的引腳外,還有控制顯示器的引腳(這個(gè)我們會(huì )在驅動(dòng)那里介紹,繼續往下看)。
結論:?jiǎn)纹瑱C芯片與顯示器相連,可以通過(guò)引腳輸出的電平來(lái)控制顯示器的字符顯示。
那么,綜合上面,也就是說(shuō),單片機芯片cpu可以通過(guò)執行指令來(lái)控制顯示器的字符顯示。
而這里,題主所說(shuō)的硬件,指的就是這個(gè)顯示器了。
接下來(lái)講驅動(dòng):
那么,什么是驅動(dòng)呢?驅動(dòng)無(wú)非就是硬件跟軟件的中間層,但我們不糾結這種關(guān)系,直接來(lái)看一下,對于我們這個(gè)例子,驅動(dòng)指的是什么。首先我們要知道:
顯示器支持很多種操作,比如說(shuō)清除顯示,光標移動(dòng),讀取數據,寫(xiě)數據等等。
這些操作數據引腳和控制引腳來(lái)實(shí)現。
引腳可以通過(guò)單片機芯片來(lái)控制。
結論:我們可以通過(guò)在單片機芯片里面寫(xiě)顯示器的“驅動(dòng)”程序來(lái)屏蔽掉硬件(顯示器硬件)層。
于是這里驅動(dòng)程序,指的是顯示器所支持操作的程序表示。比如說(shuō)清除顯示,我們可以編寫(xiě)一個(gè)clear()函數,光標移動(dòng),我們編寫(xiě)一個(gè)move_cursor()函數,讀取數據和寫(xiě)數據分別為read()和write(),然后分別實(shí)現就可以了(通過(guò)向寄存器里寫(xiě)數據的形式,進(jìn)而控制引腳的電平變化,再而控制顯示器,這個(gè)過(guò)程前面已有介紹)。這些函數就是驅動(dòng)程序了。為什么上面說(shuō)驅動(dòng)程序可以屏蔽掉硬件呢?因為程序員可以使用前面的驅動(dòng)程序來(lái)直接操作顯示器(硬件),而不用知道太多關(guān)于硬件的事情,而一般的驅動(dòng)程序也可以由廠(chǎng)家來(lái)提供。
再說(shuō)明一點(diǎn):一般這些驅動(dòng)程序可以用匯編寫(xiě)(出于運行效率的考慮),也可以用C語(yǔ)言來(lái)編寫(xiě)的,比如說(shuō)我上面的例子,就可以直接用C語(yǔ)言來(lái)編寫(xiě)。當然C語(yǔ)言?xún)嚷?lián)匯編的形式也可以。
最后講C語(yǔ)言怎么操作硬件:
相信到這里,C語(yǔ)言是怎么操作硬件的已經(jīng)比較明白了。
這里總結一下:
C語(yǔ)言由CPU運行(實(shí)際上是先編譯成機器碼存在芯片里面然后執行),可以去操作內存。
內存里有一段是跟寄存器相對應的,而寄存器是跟芯片的引腳相對應的,于是操作該段內存就能控制芯片引腳的電壓變化。
硬件(比如說(shuō)顯示器)有引腳(或者說(shuō)排線(xiàn),這些也是一樣的東西),這些引腳跟芯片的引腳相連可以接受芯片的控制。
可以把對某個(gè)硬件的操作做成一系列操作函數,這些操作函數就是驅動(dòng)程序了。
于是我們的C語(yǔ)言只要去調用這個(gè)驅動(dòng)程序就可以直接操作硬件了。(當然驅動(dòng)程序也可以由C語(yǔ)言來(lái)編寫(xiě),所以C語(yǔ)言操作硬件并不一定要經(jīng)過(guò)驅動(dòng)程序)。
【C語(yǔ)言竟是如何調用硬件】相關(guān)文章:
C語(yǔ)言如何調用硬件02-14
C語(yǔ)言是如何調用硬件的03-28
c語(yǔ)言如何控制硬件05-24
如何在c語(yǔ)言中調用Linux腳本07-09
C語(yǔ)言函數的運用及調用05-10
C語(yǔ)言函數的遞歸調用05-17
c語(yǔ)言調用系統命令06-13
如何在C/C++中調用Java03-13