之前我們把重點放在硬體 - 組成計算機的物理元件,比如電,電路,暫存器,ram,alu,cpu。但在硬體層面程式設計非常麻煩,所以程式設計師想要一種更通用的方法程式設計,一種"更軟的"媒介,沒錯,我們要講軟體!
前面我們一步步講了乙個簡單程式,第一條指令在記憶體位址 0:0010 1110,之前說過,前 4 位是操作碼,簡稱 opcode。對於這個假設 cpu,0010 代表 load_a 指令,把值從記憶體複製到暫存器 a,後 4 位是記憶體位址,1110 是十進位制的 14。所以這 8 位表達的意思是 "讀記憶體位址 14,放入暫存器 a"
只是用了兩種不同語言,可以想成是英語和摩爾斯碼的區別,"hello" 和 ".... . .-.. .-.. —",都是"你好"的意思,只是編碼方式不同。英語和摩爾斯碼的複雜度也不同,英文有 26 個字母以及各種發音,摩爾斯碼只有"點"和"線",但它們可以傳達相同的資訊,計算機語言也類似。
計算機能處理二進位制,二進位制是處理器的"母語",事實上,它們只能理解二進位制,這叫"機器語言"或"機器碼"。
在計算機早期階段,必須用機器碼寫程式,具體來講,會先在紙上用英語寫乙個"高層次版"。
在紙上寫好後,用"操作碼表"把偽**轉成二進位制機器碼,翻譯完成後,程式可以餵入計算機並執行。
你可能猜到了,很快人們就厭煩了,所以在 1940~1950 年代,程式設計師開發出一種新語言, 更可讀更高層次,每個操作碼分配乙個簡單名字,叫"助記符"。"助記符"後面緊跟資料,形成完整指令。與其用 1 和 0 寫**,程式設計師可以寫"load_a 14"。我們在前面用過這個助記符,因為容易理解得多!
當然,cpu 不知道 load_a 14 是什麼,它不能理解文字,只能理解二進位制,所以程式設計師想了乙個技巧,寫二進位制程式來幫忙,它可以讀懂文字指令,自動轉成二進位制指令,這種程式叫彙編器。彙編器讀取用"組合語言"寫的程式,然後轉成"機器碼","load_a 14" 是乙個彙編指令的例子。
隨著時間推移,彙編器有越來越多功能,讓程式設計更容易,其中乙個功能是自動分析 jump 位址,這裡有乙個前面用過的例子:注意, jump negative 指令跳到位址 5,jump 指令跳到位址 2。問題是,如果在程式開頭多加一些**,所有位址都會變,更新程式會很痛苦。
所以彙編器不用固定跳轉位址,而是讓你插入可跳轉的標籤。當程式被傳入彙編器,彙編器會自己搞定跳轉位址,程式設計師可以專心程式設計,不用管底層細節,隱藏不必要細節來做更複雜的工作,我們又提公升了一層抽象。
然而,即使彙編器有這些厲害功能,比如自動跳轉,彙編只是修飾了一下機器碼。一般來說,一條彙編指令對應一條機器指令,所以彙編碼和底層硬體的連線很緊密。
彙編器仍然強迫程式設計師思考 用什麼暫存器和記憶體位址,如果你突然要乙個額外的數,可能要改很多**讓我們想一想。
我們將在下一節講。
如何榨乾cpu的所有價值
程式如何"進入"計算機
最早期程式設計
程式設計師成長充電站
長按掃碼關注,每天五分鐘學習計算機最基礎的知識和原理
jmp指令對應的機器碼
od隨便開啟乙個記事本,彙編幾條jmp指令,可以看到如下 位址 hex 反彙編 010073b4 e9 7b9e8787 jmp 88881234 010073b9 e9 769e8787 jmp 88881234 010073be e9 719e8787 jmp 88881234 010073c3...
彙編中call指令和其對應的機器碼
call這個指令很神奇,他和別的指令不太一樣 對比下,當我們執行 mov eax,1 的時候,他的對應機器碼是 66 b8 01 00 00 00 這其中 66 b8 對應的是 mov eax,x 後面的 01 00 00 00 就是 1 在32位中的little endian了 所以說,在對mov...
收集彙編指令和機器碼的對應關係(完善中)
50 push eax 51 push ecx 52 push edx 53 push ebx 54 push esp 55 push ebp 56 push esi 57 push edi 58 pop eax 59 pop ecx 5a pop edx 5b pop ebx 5c pop esp...