上一篇結尾講到尋址能力,尋址就是定位記憶體的地址空間,相信很多人知道 XP 作業系統有記憶體 4G 的限制,因為 XP 是 32 位元的作業系統,所以最多只能尋址 2 的 32 次方字節大小的空間,剛好等於 4GB。
2 ^ 32 = 4 x 1024 x 1024 x 1024 = 4 GB
RAM 的全名是隨機存取記憶體,用於程式執行中提供 CPU 暫存資料的地方,RAM 並不能永久保存資料,電腦關機後儲存在上面的資料就會消失。
ROM 的全名是唯讀記憶體,顧名思義只能讀取不能寫入,程式燒入後就不能更改,儲存在上面的資料關閉電源後也不會消失,最常聽到的就是用於主機板的 BIOS 開機程式,還有一些外接卡例如顯示卡、網路卡等也會用到。
記憶體地址空間不單指主記憶體,還包括顯卡、網路卡、BIOS、等等,雖然這些裝置物理上是獨立的,但對於 CPU 而言他們是一個整體,都是透過總線相連,可用相同的方式進行控制,所以可以把所有的存儲器當成一的大的邏輯存儲器,這個連續的邏輯空間就稱為記憶體地址空間。
邏輯存儲器示意圖:
8086 CPU 的記憶體分配大致如下:
0000 ~ 9FFFF
A0000 ~ BFFFF
C0000 ~ FFFFF
CPU 將所有存儲器當成一個大的邏輯存儲器,這個連續的空間就稱為記憶體地址空間,而它的大小受限於 CPU 的尋址能力。
接著來看個有趣的例子,有一段 C 程式如下。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b;
int x = 0;
int y = 0;
a = (x++)+(x++);
b = (++y)+(++y);
printf("a=%d, b=%d\n", a, b); //a=1, b=4
return 0;
}
看起來 a 沒問題 0 + 1 = 1,
但 b 應該是 1 + 2 = 3,怎麼結果是 4 呢?
這其實是個 未定義行為
,C++ 標準並沒有規範這種行為編譯器該如何實作,因此不同編譯器可能有不同的結果,我們將程式反組譯來分析一下 (使用 Visual Studio)。
int a, b;
int x = 0;
011516BE mov dword ptr [x],0
int y = 0;
011516C5 mov dword ptr [y],0
011516CC mov eax,dword ptr [y] ;將 y 變數地址放進 eax
011516CF add eax,1 ;將 eax 加一 y=1
011516D2 mov dword ptr [y],eax ;將 eax 放回 y 變數
011516D5 mov ecx,dword ptr [y] ;將 y 變數地址放進 ecx
011516D8 add ecx,1 ;將 ecx 加一 y=2
011516DB mov dword ptr [y],ecx ;將 ecx 放回 y 變數
011516DE mov edx,dword ptr [y] ;將 y 變數地址放進 edx
011516E1 add edx,dword ptr [y] ;將 edx + y 等於 2 + 2
011516E4 mov dword ptr [b],edx ;將 edx 放進 b 變數,結果為 4
b = (++y) + (++y);
可以看到編譯器應該是為了優化,先將 y 變數 +1 了兩次再相加,所以結果才會等於 4,透過組合語言可以清楚看到程式是如何執行,後面有機會再找幾個常用的語法分享給大家,昨天暐翰大說期待反組譯,結果只寫這樣希望不要被打。
補充: Visual Studio C++ 專案在 Debug 模式時,按右鍵可以看到反組譯選項,會將組合語言穿插在 C++ 程式碼中,非常好用。
下一篇要開始介紹組合語言的核心,令人非常頭痛的 暫存器
,今天就到這裡摟,感謝大家觀看。
針對b = (++y) + (++y);
請問實際上正確是4還是3?
就語意上來說我要的是(1+0)+(1+1)
結論是要改code修正語意嗎?
可以參考這篇,講的很詳細
https://www.cnblogs.com/jiayouwyhit/p/3147557.html
b = (++y) + (++y);
在同個表達式中,y 被改變了多次
這種語法屬於未定義行為,使用不同編譯器可能產生不同結果
所以建議工程師不要使用
結論是要改code修正語意嗎?
恩,將程式碼拆開來寫即可
我學程式那麼久才知道有這種眉角
感激不盡
ROM的介紹那邊484打錯了
///
RAM 的全名是唯讀記憶體,顧名思義只能讀取不能寫入,程式燒入後就不能更改,儲存在上面的資料關閉電源後也不會消失,最常聽到的就是用於主機板的 BIOS 開機程式,還有一些外接卡例如顯示卡、網路卡等也會用到。
///
應該是ROM吧
真的,謝謝提醒!