程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言入門篇-02

C語言入門篇-02

編輯:關於C語言

上篇扯了許多廢話,今天就不扯廢話了,總之大家要認識到IT界是一個很龐大的體系,從做硬件,焊接電容電阻的工程師,到電路設計,到電路板制作,到軟件程序設計,到通信,網絡通信,串口通信,界面編程,WEB編程,數據庫編程,數據庫系統,音頻編程,視頻編程,安全編程,系統編程,應用程序開發,電腦城做IT銷售的,裝系統的,電腦維修的,數據恢復的,平面設計,3維設計,高級特效設計,服務器管理,網絡架設等等,而每一個具體的方向又是非常復雜,反正舉這麼多例子 並不是讓大家都了解這些,一個人的精力是有限的,我們只能攻其一個方向,但就是一個方向要搞精,不要這也學那也學,學到最後沒有學到真本事,現在中國就是不缺二流人才,缺少的是一流人才。好了,說了不扯,又扯上了。

回到正題,今天講點啥呢?我感覺,學C的人能找到我這文章,應該不是小白了,至少你懂得變量 循環 等知識了。如果這也不懂,那麼你得隨便找本書看看基本語法。

先來回顧一下01裡主機講了哪些知識點吧,對內存的認識,地址,字節,還講了整數的存儲及范圍,還有就是邏輯地址哦。今天就來講一些有關程序的細節吧。

當我們寫一個hello world的程序時,點擊組建 就會得到一個 .exe 文件,它是怎麼組織的呢?它裡面都有哪些內存呢。我們稱這樣的.exe程序為PE文件,它是微軟公司對COFF的擴展,關於COFF,大家可以http://en.wikipedia.org/wiki/COFF 查看一下它的詳細介紹,E文不好就不要看了,它是對可執行文件格式的一種規范,微軟推出自己的COFF 也就是PE,有一本叫 windows pe 權威指南,講的就是這個文件格式,不過那本書很高級,做開發的一般不需要研究太深入,了解個大概就行了,而我們要知道的就是,PE是一個文件結構,它有自己的規范,比如我們在程序中寫的代碼放在.exe文件的什麼位置,我們定義的字符串放在.exe文件的什麼地方,我們的資源文件放在.exe的什麼位置,大概了解一下就行,但是你要有個認識,就是有一種規范在約束著它,如果你的程序不符合這種規范,那麼它就不能被操作系統所認識,也就是你隨便把一個圖片改成.EXE 然後雙擊執行 ,系統是不會執行的,因為它並不認識 ,關於PE結構大家是有能力就了解,沒時間就可以不用了解了,知道它是一個什麼東西就行了。

那麼我們在加載hello world.exe 系統為它分配了哪些內存呢?這個我們先把這個給大家一個答案。

棧、堆、代碼、數據 我們暫時就可以認為是這四個主要內存塊,而且在 XP VC6 的環境下的這些地址是相對穩定的。

內存塊名字起始地址棧區0X0012E000左右,只是相對穩定堆區0X00380000左右,只是相對穩定代碼區0X00400000數據區位於代碼區高地址區

對於上表,我們沒有給出范圍大小,只給出起始地址,並不是說沒有,而是大小范圍並不一定,我們可以將光標移動到 printf 那句代碼的上面,然後按F9 下個斷點,然後按F5開始調試,這個時候,程序執行到剛才設置的斷點處,默認會彈出一個名叫調試 的小窗口(工具欄),可以拖動它,將它擺到合適的位置,小窗口中有一些按鈕,我們可以把鼠標放在上面,停一會會有提示信息,我們需要找的第一個就是memory窗口,點一下,會彈出內存數據窗口,memory窗口是可以調整大小的,建議剛開始把這個窗口接長一點,因為我們要看一下這裡面的數據。

1、觀察4G的邏輯地址空間,內存窗口有一個address(地址) 文本,在它右邊是一個編輯框,可以輸入地址,下面有三列,左邊一列就是地址,中間是地址裡面的數據(16進制),右邊一列是數據對應的ASCII字符,那麼我們可以看一下地址的范圍,為了方便 ,我們01裡講了 邏輯地址空間范圍是 從0 到 2^32-1 (32個1,就是FF FF FF FF(以後我管它叫8個F),如果看成32位有符號數的話,就是-1,什麼不會算?請看注1),所以我們只需要在編輯框裡輸入0 就可以定位到起始邏輯地址,輸入-1就可以定位到終止邏輯地址,我們可以適當的拖動一下滾動條看一下。


注1:這裡是對01知識的一個小回顧,首先這個是32位有符號數,那麼我們只需要將它們的值加起來求和就行了。

1111 1111 1111 1111 1111 1111 1111 1111

其實就是 (2^0+2^1+2^2+....+2^30)+ (-2^31) = 2^31-1 -2^31 = -1 用的還是01裡的公式哦。

當我們定位到0 或-1的時候,我們發現這些區域裡的數值都是?? ,它是什麼意義呢,還記得01裡說過地址是從物理內存映射過來的嗎,也就是邏輯地址空間是一個虛擬空間,真正的空間在物理內存裡,邏輯地址只是MMU將物理內存做了一個映射,??表示這個區域並沒有對應真實的物理內存,那麼都有哪些地址映射了物理內存呢,我們已經在上面的表格中給出來了,大家可以在編輯框中輸入 0X12E000,然後看看這個區域有沒有數據,如果沒有,那麼就在內存窗口中隨便點一下(激活窗口),按鍵盤上的PAGEDOWN 鍵,一直按,直到看到數據,然後找找這個區域的邊界,如下圖所示(圖1),是起始位置

124539502.jpg

好,我們已經看到棧區的開始位置了,接下來就是要定位棧區的結束位置了,怎麼定位呢,很好辦,還是在內存窗口中點一下以激活內存窗口,然後按鍵盤上的PAGEDOWN向下翻頁,當你看到?? 的時候就證明你已經超過了棧區的下限了,再按PAGEUP 向上 慢慢調整,最終,我們找到如下圖的位置,當然這個地址並不是固定的,也就是在你的電腦上可能不是這個地址哦。

124622661.jpg

好了,我想大家都明白了,原來棧就是一塊連續的內存,既然是內存塊就有起始地址和終止地址。

2、我們再來觀察一下堆區吧,系統默認為我們申請了一個堆區,我們使用malloc 等函數進行內存申請的時候,實際上就是在這塊區域進行申請的,那麼它在我們邏輯地址空間的哪個位置呢?讓我們稍微修改一下代碼,如下圖

124707932.jpg

然後按F5開始調試,這個時候,正常情況下程序會運行到printf 函數就暫停下來,我們將鼠標放在 p變量上,稍微停一小會,就會顯示出p的值,如果沒有顯示出來就多試幾次,在我這裡顯示p的值是0x003807b8 ,好,現在打開內存窗口,在地址編輯框中 輸入這個 地址,不要忘了0X,效果如下圖

124803316.jpg

然後我們再通過PAGEUP 向上翻頁,找這塊內存區域的上限,通過PAGEDOWN向下翻頁,找這塊內存區域的下限

上限圖

124839358.jpg

下限圖

124919594.jpg

這樣我們就定位到了第二個重要內存區域了,這個區域叫做堆區,我們用一些malloc calloc等函數就是在這個區域申請內存哦,要記住哦。

3、下面我們就要研究一下代碼區域了,其實我們寫程序的一部分就是在組織機器指令,說白了就是在做01的排列,這是最底層的理解了,那麼我們就來看看,我們寫的程序生成的機器代碼是什麼樣子的呢? 還是上面的例子,繼續在調試狀態,我們點一下調試窗口裡最後一個按鈕,叫做反匯編代碼窗口,這樣就會彈出源碼對應的反匯編代碼區域了,如下圖

124950729.jpg

在這裡,我們可以看到一些匯編指令 如 push,call ,add,mov等,我們暫時不關心它們是什麼意思,我們在這個窗口裡右擊,選中Code Bytes,然後窗口中會顯示一些額外信息,如下圖

125015784.jpg

我們會看到這裡面多了一些 16 進制數據,如圖中黑色區域(什麼,不知道我怎麼選中的,告訴你吧,按住ALT鍵 再進行選中操作,這個方法在許多軟件裡都有實現,VS裡也支持,PUTTY裡也支持,You out la),那麼它們是什麼?它們就是傳說中的機器字節碼,只不過是16進制表示的,如果你願意,你可以將它們轉成2進制哦,那可真就成了天書了,那麼在它們每行的前面都有個地址,這個地址就是邏輯地址哦,也就是說,這些字節碼現在就在我們的內存中,在什麼區域呢,在代碼區呀,,,哈哈,知道了吧,我們上面已經說了,代碼區位於0X00400000開始,我們可以看到 每行前面的地址也基本上位於這個區域范圍裡呀,現在我們就來定位一下吧

代碼區上限

125047843.jpg

代碼區下限

125213163.jpg

代碼區范圍還是比較大的

這樣子定位是不是很慢呀,有什麼較快的辦法嗎,答案是有的,記住,這些操作是在調試狀態下才有的哦,點擊菜單欄中 debug(調試),下面有個Modules(模塊),點擊會彈出對話框,如下圖

125128446.jpg

看到了吧,Hello World的地址是 0X00400000 - 0X0042BFFF 這就是代碼區域哦。

那麼有沒有想過這個問題,這些數據是從哪裡加載到內存中的呢?你能猜想出來嘛,好吧,我來告訴你,在PE文件裡,也就是我們的.EXE文件,

我們隨便記下一段指令,就記下 上面有一張圖裡有一個我選中的黑塊,就那一段指令吧,我們把程序停掉。然後點擊文件打開,彈出如下對話框

125240458.jpg

在文件類型裡,選中所有文件,Open as選成Binary,定位到 HelloWorld.exe(在Debug目錄裡哦),然後點擊打開,如果一切正常的話,會看到下圖所示的內容

125310642.jpg

我們按CTRL + F 進行搜索,搜索什麼呢,就是那個黑塊裡的內容,6A 0C E8 01 6E FF FF 83 C4 04 89 45 FC ,搜索,結果如圖

125334813.jpg

怎麼樣,理解了嗎,我們寫的程序生成的機器字節碼都被寫進了.exe裡,當操作系統加載我們的程序時,為我們的程序分配內存空間,做地址映射,將我們的字節碼加載到內存中,其實不只是機器字節碼寫進去了,字符串也被寫進去了呢,你要不相信,可以試試搜索我們printf函數輸也的字符串哦,如圖

125357795.jpg

明白了吧。這就是PE文件的簡介,反正就是要大家理解,我們寫的代碼生成的數據,代碼,資源等都被寫入了PE文件裡啦,也就是他們是有組織有紀律的一個標准的文件,你不會忘了我們前面講過的有規范約束著它呢吧。

好,還有一個就是數據區了,數據區相對來說比較簡單,當我們在程序中定義一些全局變量,在函數裡定義一些靜態變量,這些變量是存在於靜態數據區的,我們來演示一下。

修改代碼,結果演示如下圖

125435618.jpg

在地址欄輸入全局變量名字,會定位到我們的全局變量的地址,我們可以清楚的看到它們的值

還記得小端模式嗎,我們定義的是 0X99887766,但是它在內存窗口顯示的卻是66 77 88 99 這就是小端模式,而且後面的兩個數值也可以看到了,一個就是0X11223344,另一個就是0X55667788,是我們定義的兩個其它的靜態變量,如果直接在地址欄裡輸入val,它是計算不出地址的,一定要寫全局變量的名字才行哦。我們重點是關心它們的地址,在0X00427318,其實就是在代碼區域的大地址端。

好了,這一節就介紹這麼多,我感覺如果你把這些理解透了,你的根基可以說是非常牢了,我的建議是希望大家把基礎打牢,有句話講的好呀,基礎不牢,地動山搖。哈哈,玩笑開大了,,,今天說的這些並不是要大家全記下來,關鍵是理解好程序的分區,至於幾個區域的作用,我們以後再講哦。88再見!!!!!!!!!!!!!




本文出自 “千千阙歌” 博客,請務必保留此出處http://qianqianquege.blog.51cto.com/8004200/1304552

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved