當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]Part 1. 機(jī)器指令 上一次 我們已經(jīng)了解了 二進(jìn)制和 CPU 的基本原理,知道了程序運(yùn)行時(shí),CPU 每秒數(shù)以億次、十億次、百億次地震蕩著時(shí)鐘,同步執(zhí)行著微小的 「電子操作」,例如:從內(nèi)存讀取一個(gè)字節(jié)的數(shù)據(jù)到 CPU 又或者判斷字節(jié)中的某一位是 0 還是 1。 CPU 本

Part 1. 機(jī)器指令

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

上一次 我們已經(jīng)了解了 二進(jìn)制和 CPU 的基本原理,知道了程序運(yùn)行時(shí),CPU 每秒數(shù)以億次、十億次、百億次地震蕩著時(shí)鐘,同步執(zhí)行著微小的 「電子操作」,例如:從內(nèi)存讀取一個(gè)字節(jié)的數(shù)據(jù)到 CPU 又或者判斷字節(jié)中的某一位是 0 還是 1。

CPU 本身有一組 規(guī)定好的 可以執(zhí)行的 「基本動(dòng)作」(被稱為 機(jī)器指令):

  1. 讀取指令;2. 執(zhí)行指令;3. 寫寄存器;

這幾乎就是 CPU 工作的全部了。 這些動(dòng)作雖然每次只能執(zhí)行一次,但是每秒可以執(zhí)行數(shù)十億次,這個(gè)數(shù)量級(jí)的「小操作」累加成為一個(gè)大的「有用的操作」。

處理器所做的一切都是基于這些微小的操作!幸運(yùn)的是,我們已經(jīng)不再需要了解這些操作的詳細(xì)信息就可以編寫和使用各類程序。諸如 Java 這一類的 「高級(jí)語(yǔ)言」目的 就是 將這些微小的電子操作組織成由人類可讀的「程序語(yǔ)言」表示的大型有用單元。

機(jī)器指令演示

一條 機(jī)器指令 一般由內(nèi)存中的幾個(gè)字節(jié)組成,它們告訴 CPU 應(yīng)該執(zhí)行一個(gè)什么樣的 「機(jī)器操作」(是取數(shù)據(jù)還是寫寄存器等..)。處理器依次查看 CPU 中的機(jī)器指令,并執(zhí)行每一條。內(nèi)存中的一組機(jī)器指令被稱為 「機(jī)器語(yǔ)言程序」,或稱為 「可執(zhí)行程序」

下面我們來(lái)使用機(jī)器語(yǔ)言來(lái)演示一個(gè)控制燈泡亮度的機(jī)器語(yǔ)言程序。

先和硬件做好規(guī)定

假設(shè)燈泡由內(nèi)存中的某一個(gè)程序控制,該程序能夠完全打開(kāi)和關(guān)閉燈泡,可以使燈泡變亮或變暗,機(jī)器指令一個(gè)字節(jié)長(zhǎng)度,并且與機(jī)器操作對(duì)應(yīng)如下:

機(jī)器指令 機(jī)器操作
00000000 停止程序
00000001 完全打開(kāi)燈泡
00000010 完全關(guān)閉燈泡
00000100 燈泡暗淡 10%
00001000 將燈泡照亮 10%
00010000 如果燈泡完全點(diǎn)亮,則跳過(guò)下一條說(shuō)明
00100000 如果燈泡完全熄滅,請(qǐng)?zhí)^(guò)下一條說(shuō)明
01000000 轉(zhuǎn)到程序的開(kāi)始(地址 0)

Demo 程序 && 演示

根據(jù)上方作出的規(guī)定,我們寫下如下的程序:(為了方便理解,我把對(duì)應(yīng)的機(jī)器操作也寫在了后面,實(shí)際的程序只包含機(jī)器指令)

地址 機(jī)器指令 機(jī)器操作
0 00000001 完全打開(kāi)燈泡
1 00000010 完全關(guān)閉燈泡
2 00000001 完全打開(kāi)燈泡
3 00000100 燈泡暗淡10%
4 00000100 燈泡暗淡10%
5 00000000 停止程序

所以這樣的一段程序執(zhí)行效果就如下圖:

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

您可以嘗試自己利用 01000000(跳轉(zhuǎn)到程序開(kāi)始) 來(lái)改寫程序來(lái)達(dá)到讓「燈逐漸變亮又逐漸變暗」的目的。

小結(jié)

上面演示的程序 核心思想 是:

  • 機(jī)器語(yǔ)言程序是內(nèi)存中一系列機(jī)器指令的集合;
  • 機(jī)器指令由一個(gè)或多個(gè)字節(jié)組成(在此示例中,僅一個(gè)字節(jié));
  • 處理器一次運(yùn)行一條機(jī)器指令的程序;
  • 所有的小機(jī)器操作加起來(lái)都是有用的;

在實(shí)際的 CPU 中,擁有更多的機(jī)器指令,而且更詳細(xì),并且不同的 CPU,指令集是不同的。典型的 CPU 擁有一千或更多的機(jī)器指令。

Part 2. 匯編語(yǔ)言

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!
  • 圖片來(lái)源:http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html

機(jī)器語(yǔ)言太 "反人類”

我們已經(jīng)可以開(kāi)始寫一些程序使用了,但是使用 機(jī)器語(yǔ)言編寫代碼會(huì)十分辛苦,比如:

00000001 00000010 00000001
00000100 00000100 00000000

即使你剛看過(guò)你也會(huì)對(duì)這一段就在 上方的實(shí)例代碼 沒(méi)有什么感知,這是因?yàn)闄C(jī)器語(yǔ)言是設(shè)計(jì)給機(jī)器的,人類記憶和使用起來(lái)就會(huì)顯得十分麻煩。

如此你就會(huì)感知到 上個(gè)世紀(jì) 的程序員使用 打孔卡片

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

使用 紙帶

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

甚至是 直接插拔線路 or 按下開(kāi)關(guān)

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

是一件多么硬核的事情...

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

如果你對(duì)它們?nèi)绾喂ぷ饕约岸嗝从埠烁信d趣,可以參考一下下方的鏈接:

  • 開(kāi)發(fā)語(yǔ)言小傳之一:最早的編程語(yǔ)言——機(jī)器語(yǔ)言 - https://blog.csdn.net/killer080414/article/details/42219091
  • 50年前的登月程序和程序員有多硬核 - https://coolshell.cn/articles/19612.html、

再附帶一個(gè)寶藏網(wǎng)站(哥倫比亞大學(xué)出版的計(jì)算機(jī)歷史,非常詳細(xì)),有條件的同學(xué) 非常推薦 進(jìn)去瀏覽一下:

  • http://www.columbia.edu/cu/computinghistory/index.html

匯編語(yǔ)言誕生

CPU 的指令都是 二進(jìn)制 的,這顯然對(duì)于人類來(lái)說(shuō)是 不可讀 的。為了解決二進(jìn)制指令的可讀性問(wèn)題,工程師將那些指令寫成了 八進(jìn)制。二進(jìn)制轉(zhuǎn)八進(jìn)制是輕而易舉的,但是八進(jìn)制的可讀性也不行。

很自然地,最后還是用文字表達(dá),加法指令寫成 ADD。內(nèi)存地址也不再直接引用,而是 用標(biāo)簽 表示。

這樣的話,就多出一個(gè)步驟,要把這些文字指令翻譯成二進(jìn)制,這個(gè)步驟就稱為 assembling,完成這個(gè)步驟的程序就叫做 assembler。它處理的文本,自然就叫做 aseembly code。標(biāo)準(zhǔn)化以后,稱為 assembly language,縮寫為 asm,中文譯為 匯編語(yǔ)言。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!
  • 圖片來(lái)源:http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html

理解匯編語(yǔ)言

每一種 CPU 的機(jī)器指令都是不一樣的,因此對(duì)應(yīng)的匯編語(yǔ)言也不一樣。本文介紹的是目前最常見(jiàn)的 x86 匯編語(yǔ)言,即 Intel 公司的 CPU 使用的那一種。

寄存器

要學(xué)習(xí)匯編語(yǔ)言,首先必須了解兩個(gè)知識(shí)點(diǎn):寄存器內(nèi)存模型。

先來(lái)看寄存器。CPU 本身只負(fù)責(zé)運(yùn)算,不負(fù)責(zé)儲(chǔ)存數(shù)據(jù)。數(shù)據(jù)一般都儲(chǔ)存在內(nèi)存之中,CPU 要用的時(shí)候就去內(nèi)存讀寫數(shù)據(jù)。但是,CPU 的運(yùn)算速度遠(yuǎn)高于內(nèi)存的讀寫速度,為了避免被拖慢,CPU 都自帶一級(jí)緩存和二級(jí)緩存。基本上,CPU 緩存可以看作是讀寫速度較快的內(nèi)存。

但是,CPU 緩存還是不夠快,另外數(shù)據(jù)在緩存里面的地址是不固定的,CPU 每次讀寫都要尋址也會(huì)拖慢速度。因此,除了緩存之外,CPU 還自帶了寄存器(register),用來(lái)儲(chǔ)存最常用的數(shù)據(jù)。也就是說(shuō),那些最頻繁讀寫的數(shù)據(jù)(比如循環(huán)變量),都會(huì)放在寄存器里面,CPU 優(yōu)先讀寫寄存器,再由寄存器跟內(nèi)存交換數(shù)據(jù)。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

寄存器不依靠地址區(qū)分?jǐn)?shù)據(jù),而依靠名稱。每一個(gè)寄存器都有自己的名稱,我們告訴 CPU 去具體的哪一個(gè)寄存器拿數(shù)據(jù),這樣的速度是最快的。有人比喻寄存器是 CPU 的零級(jí)緩存。

寄存器的種類

早期的 x86 CPU 只有 8 個(gè)寄存器,而且每個(gè)都有不同的用途?,F(xiàn)在的寄存器已經(jīng)有 100 多個(gè)了,都變成通用寄存器,不特別指定用途了,但是早期寄存器的名字都被保存了下來(lái)。

  • EAX
  • EBX
  • ECX
  • EDX
  • EDI
  • ESI
  • EBP
  • ESP

上面這 8 個(gè)寄存器之中,前面七個(gè)都是通用的。ESP 寄存器有特定用途,保存當(dāng)前 Stack 的地址(詳見(jiàn)下一節(jié))。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

我們常常看到 32 位 CPU、64 位 CPU 這樣的名稱,其實(shí)指的就是寄存器的大小。32 位 CPU 的寄存器大小就是 4 個(gè)字節(jié)。

內(nèi)存模型:Heap(堆)

寄存器只能存放很少量的數(shù)據(jù),大多數(shù)時(shí)候,CPU 要指揮寄存器,直接跟內(nèi)存交換數(shù)據(jù)。所以,除了寄存器,還必須了解內(nèi)存怎么儲(chǔ)存數(shù)據(jù)。

程序運(yùn)行的時(shí)候,操作系統(tǒng)會(huì)給它分配一段內(nèi)存,用來(lái)儲(chǔ)存程序和運(yùn)行產(chǎn)生的數(shù)據(jù)。這段內(nèi)存有起始地址和結(jié)束地址,比如從 0x10000x8000,起始地址是較小的那個(gè)地址,結(jié)束地址是較大的那個(gè)地址。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

程序運(yùn)行過(guò)程中,對(duì)于動(dòng)態(tài)的內(nèi)存占用請(qǐng)求(比如新建對(duì)象,或者使用 malloc 命令),系統(tǒng)就會(huì)從預(yù)先分配好的那段內(nèi)存之中,劃出一部分給用戶,具體規(guī)則是從起始地址開(kāi)始劃分(實(shí)際上,起始地址會(huì)有一段靜態(tài)數(shù)據(jù),這里忽略)。舉例來(lái)說(shuō),用戶要求得到 10 個(gè)字節(jié)內(nèi)存,那么從起始地址 0x1000 開(kāi)始給他分配,一直分配到地址 0x100A,如果再要求得到 22 個(gè)字節(jié),那么就分配到 0x1020。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

這種因?yàn)橛脩糁鲃?dòng)請(qǐng)求而劃分出來(lái)的內(nèi)存區(qū)域,叫做 Heap(堆)。它由起始地址開(kāi)始,從低位(地址)向高位(地址)增長(zhǎng)。Heap 的一個(gè)重要特點(diǎn)就是不會(huì)自動(dòng)消失,必須手動(dòng)釋放,或者由垃圾回收機(jī)制來(lái)回收。

內(nèi)存模型:Stack(棧)

除了 Heap 以外,其他的內(nèi)存占用叫做 Stack(棧)。簡(jiǎn)單說(shuō),Stack 是由于 函數(shù)運(yùn)行臨時(shí)占用 的內(nèi)存區(qū)域。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

例如我們?cè)趫?zhí)行一個(gè)叫 main 的函數(shù)時(shí),會(huì)為它在內(nèi)存里面創(chuàng)建一個(gè) ,用來(lái)保存所有 main 中使用的內(nèi)部變量。main 函數(shù)執(zhí)行結(jié)束后,該幀就會(huì)被回收,釋放所有的內(nèi)部變量,不再占用空間。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

如果在 main 函數(shù) 內(nèi)部調(diào)用了其他函數(shù),例如 add_a_and_b 函數(shù),那么執(zhí)行到這一行的時(shí)候,系統(tǒng)也會(huì)為 add_a_and_b 新建一個(gè)幀,用來(lái)儲(chǔ)存它的內(nèi)部變量。也就是說(shuō),此時(shí)同時(shí)存在兩個(gè)幀:mainadd_a_and_b。一般來(lái)說(shuō),調(diào)用棧有多少層,就有多少幀。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

等到 add_a_and_b 運(yùn)行結(jié)束,它的幀就會(huì)被回收,系統(tǒng)會(huì)回到函數(shù) main 剛才中斷執(zhí)行的地方,繼續(xù)往下執(zhí)行。通過(guò)這種機(jī)制,就實(shí)現(xiàn)了函數(shù)的 層層調(diào)用,并且 每一層都能使用自己的本地變量。

我們可以把棧理解為一個(gè)下方密封,而上方打開(kāi)的「桶」。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

生成的新幀放入我們稱之為 「入?!?/strong>,而釋放幀我們稱之為 「出棧」棧的特點(diǎn) 就是,最晚入棧的幀最早出棧(因?yàn)樽顑?nèi)層的函數(shù)調(diào)用,最先結(jié)束運(yùn)行),這就叫做 "后進(jìn)先出" 的數(shù)據(jù)結(jié)構(gòu)。每一次函數(shù)執(zhí)行結(jié)束,就自動(dòng)釋放一個(gè)幀,所有函數(shù)執(zhí)行結(jié)束,整個(gè)棧就都釋放了。

匯編語(yǔ)言演示

舉個(gè)簡(jiǎn)單的例子,我們需要計(jì)算:

(1 + 4) * 2 + 3

我們按照 「后綴表示法」 進(jìn)行一下轉(zhuǎn)換:

1,4,+,2,*,3,+

我們平常使用的方法是 「中綴表示法」,也就是把計(jì)算符號(hào)放中間,例如 1 + 3,后綴則是把符號(hào)放最后,例如 1, 3, +。

這樣做的好處是沒(méi)有先乘除后加減的影響,也沒(méi)有括號(hào),直接運(yùn)算就行了。(例如 1, 3, +,先把 13 保存起來(lái)碰到 + 知道是加法則直接相加)

OK,我們從頭開(kāi)始使用匯編語(yǔ)言來(lái)編寫一下程序,首先第一步:把 1 保存起來(lái)(放入寄存器):

MOV  1

之后是 4, +,那就直接加一下:

ADD 4

然后是 2, *,那就直接乘一下(SHL 是向左移動(dòng)一位的意思,二進(jìn)制中左移一個(gè)單位就相當(dāng)于乘以 2,例如 01 表示 1,而 10 則表示 2):

SHL 0

最后是 3, +,再加一下:

ADD 3

完整程序如下:

MOV  1
ADD 4
SHL 0
ADD 3

這似乎看起來(lái)比 00001111 這樣的二進(jìn)制要好上太多了!程序員們感動(dòng)到落淚:

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

Part 3. 高級(jí)編程語(yǔ)言

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

擺脫了 二進(jìn)制,我們有了更可讀的 匯編語(yǔ)言,但仍然十分繁瑣和復(fù)雜,每一條匯編指令代表一個(gè)基本操作,例如:「從內(nèi)存 x 位置獲取一個(gè)數(shù)字并放入寄存器 A」、「將寄存器 A 中的數(shù)字添加到寄存器 B 的數(shù)字上」。這樣的編程風(fēng)格既費(fèi)時(shí)又容易出錯(cuò),并且一旦出錯(cuò)還很難發(fā)現(xiàn)。

例如,我們來(lái)看一看 「1969 年阿波羅 11號(hào)登月計(jì)劃」 用來(lái) 防止登月艙計(jì)算機(jī)耗盡自身資源 的 BAILOUT 代碼:

POODOO    INHINT
CA Q
TS ALMCADR

TC BANKCALL
CADR VAC5STOR # STORE ERASABLES FOR DEBUGGING PURPOSES.

INDEX ALMCADR
CAF 0
ABORT2 TC BORTENT

OCT77770 OCT 77770 # DONT MOVE
CA V37FLBIT # IS AVERAGE G ON
MASK FLAGWRD7
CCS A
TC WHIMPER -1 # YES. DONT DO POODOO. DO BAILOUT.

TC DOWNFLAG
ADRES STATEFLG

TC DOWNFLAG
ADRES REINTFLG

TC DOWNFLAG
ADRES NODOFLAG

TC BANKCALL
CADR MR.KLEAN
TC WHIMPER
  • 出處:改變世界的代碼行 - https://www.infoq.cn/article/5CaYH8NbS6BmptWKRgkX

似乎不太容易讀的樣子...

阿波羅登月計(jì)劃的源代碼在 Github 上已經(jīng)公開(kāi),有興趣的可以去下方鏈接膜拜一下(可以去感受一下當(dāng)時(shí)程序員的工程能力):

  • https://github.com/chrislgarry/Apollo-11

另外附一下當(dāng)時(shí)代碼的設(shè)計(jì)負(fù)責(zé)人 Margaret Heafield Hamilton(女程序員)和完成的堆起來(lái)跟人一樣高的代碼量:機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

第一個(gè)高級(jí)語(yǔ)言:FORTRAN

當(dāng) John Backus1950 年以一名科學(xué)程序員的身份加入 IBM 時(shí),已經(jīng)可以使用諸如 ADD 之類的助記詞代替數(shù)字代碼來(lái)編寫程序,也就是我們的匯編語(yǔ)言。這使編程變得容易一些,但是即使是一個(gè)簡(jiǎn)單的程序也需要數(shù)十次操作,并且仍然很難找到錯(cuò)誤。

巴克斯認(rèn)為,應(yīng)該有可能創(chuàng)建一種編程語(yǔ)言,使一系列計(jì)算可以用類似于數(shù)學(xué)符號(hào)的形式來(lái)表達(dá)。然后,使用特定的翻譯程序(以今天的術(shù)語(yǔ)來(lái)說(shuō)是編譯器)可以將其轉(zhuǎn)換為計(jì)算機(jī)可以理解的數(shù)字代碼。

Backus 在 1953 年向他的經(jīng)理提出了這個(gè)想法。他得到了預(yù)算,并被鼓勵(lì)雇用一個(gè)小團(tuán)隊(duì)來(lái)測(cè)試該想法的可行性。三年后,該團(tuán)隊(duì)發(fā)布了一本手冊(cè),其中描述了 IBM Mathematical Formula Translating System(簡(jiǎn)稱 FORTRAN)。不久之后, IBM 向 IBM 704 的用戶提供了第一個(gè) FORTRAN 編譯器。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!
FORTRAN 之父

Backus 和他的團(tuán)隊(duì)創(chuàng)造了世界上第一種高級(jí)編程語(yǔ)言。科學(xué)家和工程師將不再需要將其程序編寫為數(shù)字代碼或冗長(zhǎng)的助記符。

FORTRAN 代碼演示

下面演示計(jì)算并輸出 8 * 6 的代碼實(shí)例:

program VF0944
implicit none

integer a, b, c
a= 8
b= 6
c= a*b

print *, 'Hello World, a, b, c= ', a, b, c
end program VF0944

對(duì)比匯編代碼,是不是看上去要清晰(人類可讀)多了呢?

FORTRAN 的意義

FORTRAN 的問(wèn)世在計(jì)算機(jī)史上具有劃時(shí)代的意義,它使計(jì)算機(jī)語(yǔ)言從原始的低級(jí)匯編語(yǔ)言走出來(lái),進(jìn)入了更高的境界,使得 計(jì)算機(jī)語(yǔ)言不再是計(jì)算機(jī)專家的專利,使廣大的工程技術(shù)人員有了進(jìn)行計(jì)算機(jī)編程的手段。

由此計(jì)算機(jī)更快地深入到了社會(huì)之中,它在工業(yè)部門中初露頭角,更是在火箭、導(dǎo)彈、人造地球衛(wèi)星的設(shè)計(jì)中大顯身手,因此有人稱 FORTRAN 語(yǔ)言使計(jì)算機(jī)的工業(yè)應(yīng)用成了可能,是推動(dòng)第二次世界大戰(zhàn)以后西方工業(yè)經(jīng)濟(jì)復(fù)蘇和進(jìn)入第二次工業(yè)革命的無(wú)形力量,是 "看不見(jiàn)的蒸汽機(jī)"。

FORTRAN 后時(shí)代

FORTRAN 高級(jí)程序設(shè)計(jì)語(yǔ)言的出現(xiàn)孕育了計(jì)算機(jī)軟件業(yè),繼其之后,計(jì)算機(jī)高級(jí)程序語(yǔ)言的開(kāi)發(fā)進(jìn)入到了一個(gè)蓬勃發(fā)展的時(shí)代。

1959

Grace Hopper 發(fā)明了第一個(gè)面向企業(yè)業(yè)務(wù)的編程語(yǔ)言,又稱 “面向商業(yè)的通用語(yǔ)言”,也常常簡(jiǎn)稱 COBOL。

1964

美國(guó)達(dá)特茅斯學(xué)院約翰·凱梅尼和托馬斯·卡茨認(rèn)為,像 FORTRAN 那樣的語(yǔ)言太過(guò)專業(yè),編程非常困難。于是他們簡(jiǎn)化了 FORTRAN,并設(shè)計(jì)出了更適合初學(xué)者的 BASIC 語(yǔ)言。

1970

尼古拉斯·沃斯非常癡迷于編程語(yǔ)言,他率先提出了結(jié)構(gòu)化程序設(shè)計(jì)思想并發(fā)明了 Pascal 語(yǔ)言。

此外他還提出了 Wirth 定律,意為 “軟件變慢的速度比硬件變快的速度更快”,這讓摩爾定律變得充滿諷刺。之后的 Electron.js 也確實(shí)證明了這一點(diǎn)。

1972

丹尼斯·里奇在貝爾實(shí)驗(yàn)室工作期間發(fā)明了 C 語(yǔ)言,開(kāi)啟了現(xiàn)代程序語(yǔ)言的革命。之后,他又添加了段錯(cuò)誤和其他一些幫助開(kāi)發(fā)人員的實(shí)用功能,大大提升了編程效率。

除了 C 語(yǔ)言之外, 他和貝爾實(shí)驗(yàn)室的同事還創(chuàng)造了偉大的 Unix 操作系統(tǒng)。

1980

Alan Kay 發(fā)明了面向?qū)ο蟮木幊陶Z(yǔ)言 Smalltalk,在 Smalltalk 中,一切皆對(duì)象。

1987

拉里·沃爾發(fā)明了 Perl 語(yǔ)言。

1983

Jean Ichbiah 發(fā)現(xiàn) Ada Lovelace 的程序從未運(yùn)行成功過(guò),因此決定用她的名字創(chuàng)建一種語(yǔ)言,于是 Ada 語(yǔ)言誕生了。

1986

Brac Box 和 Tol Move 通過(guò)融合 C 語(yǔ)言和 Smalltalk 的特征,發(fā)明了 Objective-C。但由于其語(yǔ)法晦澀,不太容易理解。

1983

Bjarne Stroustrup 在 C 語(yǔ)言的基礎(chǔ)上引入并擴(kuò)充了面向?qū)ο蟮母拍?,發(fā)明了—種新的程序語(yǔ)言并將其命名為 C++。

C++ 大大提升了應(yīng)用程序的編程效率。

1991

Guido van Rossum 討厭帶有大括號(hào)的編程語(yǔ)言,于是他參考 Monty Python 和 Flying Circus 語(yǔ)法,并發(fā)明了 Python。

1993

Roberto Ierusalimschy 和其朋友創(chuàng)造了一門巴西本地的腳本語(yǔ)言。在本地化過(guò)程中,由于一個(gè)小的錯(cuò)誤使得索引從1開(kāi)始,而不是0。這門語(yǔ)言就是 Lua。

1994

Rasmus Lerdorf 為他個(gè)人主頁(yè)的 CGI 腳本制作了一個(gè)模板引擎,用來(lái)統(tǒng)計(jì)他自己網(wǎng)站的訪問(wèn)量。

這個(gè)文件被上傳到網(wǎng)上之后用它的人越來(lái)越多。后來(lái)又用 C 語(yǔ)言重新編寫,還添加了數(shù)據(jù)庫(kù)訪問(wèn)功能。這門語(yǔ)言就是 PHP。

1995

松本行弘發(fā)明了 Ruby 語(yǔ)言。

1995

Brendan Eich 利用周末時(shí)間設(shè)計(jì)了一種語(yǔ)言,用于為世界各地的網(wǎng)頁(yè)瀏覽器提供支持,并最終推出了 Skynet。他最初去了 Netscape,并將這門語(yǔ)言命名為 LiveScript,后來(lái)在代碼審查期間 Java 逐漸開(kāi)始風(fēng)靡,因此他們決定將其改名為 JavaScript。

后來(lái) Java 使其陷入了商標(biāo)麻煩,于是 JavaScript 被更名為 ECMAScript。但是人們還是習(xí)慣稱之為 JavaScript。

1996

James Gosling 發(fā)明了 Java,這是 第一個(gè)真正意義上面向?qū)ο蟮镁幊陶Z(yǔ)言,其中設(shè)計(jì)模式在實(shí)用主義中占統(tǒng)治地位。

More...

對(duì)于這一段計(jì)算機(jī)歷史感興趣的同學(xué)可以拜讀一下「IT 通史 12.2 節(jié) - 高級(jí)計(jì)算機(jī)程序設(shè)計(jì)語(yǔ)言」的內(nèi)容,在線預(yù)覽鏈接如下:

  • https://books.google.com.hk/books?id=ZrAol3RzcNkC&printsec=frontcover&hl=zh-CN#v=onepage&q&f=false

高級(jí)語(yǔ)言分類

CPU 終究只認(rèn)識(shí)二進(jìn)制指令,在我們發(fā)明高級(jí)語(yǔ)言之后,仍然無(wú)可避免的需要進(jìn)行 「翻譯」 工作。按照翻譯方式的不同,我們又把高級(jí)語(yǔ)言分為了 「編譯型」「解釋型」。

編譯型

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

編譯型專業(yè)解釋為:

使用 專門的編譯器,針對(duì) 特定的平臺(tái),將高級(jí)語(yǔ)言源代碼 一次性 的編譯成可被該平臺(tái)硬件執(zhí)行的機(jī)器碼,并包裝成該平臺(tái)所能識(shí)別的可執(zhí)行性程序的格式,并且只需要編譯一次,以后再也不用編譯。其實(shí)可以簡(jiǎn)單理解成谷歌/ 百度翻譯,我們把要翻譯的文字全部放進(jìn)去,一次翻譯,下次使用直接使用上一次翻譯好的結(jié)果。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!
  • 優(yōu)點(diǎn)(較解釋型):執(zhí)行效率高(有解釋器省去很多翻譯的過(guò)程)
  • 缺點(diǎn)(較解釋型):開(kāi)發(fā)效率低(寫完所有的代碼才能檢查 bug,得多恐怖呀???)

解釋型

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

解釋型專業(yè)解釋為:

使用 專門的解釋器 對(duì)源程序逐行解釋成 特定平臺(tái) 的機(jī)器碼并 立即執(zhí)行,它不需要事先編譯,直接將代碼解釋稱機(jī)器碼直接運(yùn)行,也就是說(shuō)只要某一平臺(tái)提供了相應(yīng)的解釋器即可運(yùn)行代碼。其實(shí)可以理解成同聲傳譯,我們需要翻譯的時(shí)候,找一個(gè)翻譯員,對(duì)方說(shuō)一句翻譯員翻譯一句,下次翻譯還是需要一個(gè)翻譯員一句一句的翻譯。

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!
  • 缺點(diǎn)(較編譯型):執(zhí)行效率低(寫一次翻譯一次)
  • 優(yōu)點(diǎn)(較編譯型):開(kāi)發(fā)效率高(寫一行翻譯一行,錯(cuò)了馬上就知道,媽媽再也不用擔(dān)心我找不到 bug 了)

半解釋半編譯的 Java

不同廠商、不同時(shí)間開(kāi)發(fā)的 CPU 的指令集是不一樣的,這就是上方為什么提到要使用 專門的解釋器,要用于 特定的平臺(tái) 的原因。

所以 Java 為了實(shí)現(xiàn) 「一次編譯,到處運(yùn)行」 的目的,采用了一種特別的方案:先 編譯與任何具體及其環(huán)境及操作系統(tǒng)環(huán)境無(wú)關(guān)的中間代碼(也就是 .class 字節(jié)碼文件),然后交由各個(gè)平臺(tái)特定的 Java 解釋器(也就是 JVM)來(lái)負(fù)責(zé) 解釋 運(yùn)行。

編程人員和計(jì)算機(jī)都無(wú)法直接讀懂字節(jié)碼文件,它必須由專用的 Java 解釋器來(lái)解釋執(zhí)行,因此 Java 是一種在 編譯基礎(chǔ)上進(jìn)行解釋運(yùn)行 的語(yǔ)言。(Java 程序運(yùn)行流程如下)

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

Java 解釋器 負(fù)責(zé)將字節(jié)碼文件翻譯成具體硬件環(huán)境和操作系統(tǒng)平臺(tái)下的機(jī)器代碼,以便執(zhí)行。因此 Java 程序不能直接運(yùn)行在現(xiàn)有的操作系統(tǒng)平臺(tái)上,它必須運(yùn)行在被稱為 Java 虛擬機(jī)的軟件平臺(tái)之上。

Java 虛擬機(jī)(JVM) 是運(yùn)行 Java 程序的軟件環(huán)境(我們后面會(huì)詳細(xì)說(shuō)到,這是學(xué)習(xí) Java 繞不過(guò)的題),Java 解釋器是 Java 虛擬機(jī)的一部分。在運(yùn)行 Java 程序時(shí),首先會(huì)啟動(dòng) JVM,然后由它來(lái)負(fù)責(zé)解釋執(zhí)行 Java 的字節(jié)碼程序,并且 Java 字節(jié)碼程序只能運(yùn)行于 JVM 之上。這樣利用 JVM 就可以把 Java 字節(jié)碼程序和具體的硬件平臺(tái)以及操作系統(tǒng)環(huán)境分隔開(kāi)來(lái),只要在不同的計(jì)算機(jī)上安裝了針對(duì)特定平臺(tái)的 JVM,Java 程序就可以運(yùn)行,而不用考慮當(dāng)前具體的硬件平臺(tái)及操作系統(tǒng)環(huán)境,也不用考慮字節(jié)碼文件是在何種平臺(tái)上生成的。

JVM 把這種不同軟、硬件平臺(tái)的具體差別隱藏起來(lái),從而 實(shí)現(xiàn)了真正的二進(jìn)制代碼級(jí)的跨平臺(tái)移植。JVM 是 Java 平臺(tái)架構(gòu)的基礎(chǔ),Java 的跨平臺(tái)特性正是通過(guò)在 JVM 中運(yùn)行 Java 程序?qū)崿F(xiàn)的。Java 的這種運(yùn)行機(jī)制可以通過(guò)下圖來(lái)說(shuō)明:

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

Java 語(yǔ)言這種「一次編寫,到處運(yùn)行」的方式,有效地解決了目前大多數(shù)高級(jí)程序設(shè)計(jì)語(yǔ)言需要針對(duì)不同系統(tǒng)來(lái)編譯產(chǎn)生不同機(jī)器代碼的問(wèn)題,即硬件環(huán)境和操作平臺(tái)的異構(gòu)問(wèn)題,大大降低了程序開(kāi)發(fā)、維護(hù)和管理的開(kāi)銷。

  • 提示: Java 程序通過(guò) JVM 可以實(shí)現(xiàn)跨平臺(tái)特性,但 JVM 是不跨平臺(tái)的。也就是說(shuō), 不同操作系統(tǒng)之上的 JVM 是不同的,Windows 平臺(tái)之上的 JVM 不能用在 Linux 平臺(tái),反之亦然。

參考資料

  1. Introduction to Computer Science using Java | CHAPTER 4 - http://programmedlessons.org/Java9/chap04/ch04_01.html
  2. 匯編語(yǔ)言入門教程 - http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html
  3. CPU 是怎么認(rèn)識(shí)代碼的?| 知乎@Zign - https://www.zhihu.com/question/348237008/answer/843382847
  4. 改變世界的代碼行 - https://www.infoq.cn/article/5CaYH8NbS6BmptWKRgkX
  5. The History of FORTRAN - https://www.obliquity.com/computer/fortran/history.html
  6. 《IT 通史》 | @李彥
  7. A Brief Totally Accurate History Of Programming Languages - https://medium.com/commitlog/a-brief-totally-accurate-history-of-programming-languages-cd93ec806124
  8. 編程語(yǔ)言分類 - https://www.cnblogs.com/nickchen121/p/10722720.html

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

長(zhǎng)按訂閱更多精彩▼

機(jī)器指令到匯編再到高級(jí)編程語(yǔ)言!

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉