在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

你們知道計算機是如何識別你寫的代碼的嗎?

strongerHuang ? 來源:博客園阮一峰 ? 作者:博客園阮一峰 ? 2021-07-06 10:03 ? 次閱讀

學習編程其實就是學高級語言,即那些為人類設計的計算機語言。

但是,計算機不理解高級語言,必須通過編譯器轉成二進制代碼,才能運行。學會高級語言,并不等于理解計算機實際的運行步驟。

計算機真正能夠理解的是低級語言,它專門用來控制硬件。匯編語言就是低級語言,直接描述/控制 CPU 的運行。如果你想了解 CPU 到底干了些什么,以及代碼的運行步驟,就一定要學習匯編語言。

匯編語言不容易學習,就連簡明扼要的介紹都很難找到。下面我嘗試寫一篇最好懂的匯編語言教程,解釋 CPU 如何執行代碼。

一、匯編語言是什么?我們知道,CPU 只負責計算,本身不具備智能。你輸入一條指令(instruction),它就運行一次,然后停下來,等待下一條指令。

這些指令都是二進制的,稱為操作碼(opcode),比如加法指令就是00000011。編譯器的作用,就是將高級語言寫好的程序,翻譯成一條條操作碼。

對于人類來說,二進制程序是不可讀的,根本看不出來機器干了什么。為了解決可讀性的問題,以及偶爾的編輯需求,就誕生了匯編語言。

匯編語言是二進制指令的文本形式,與指令是一一對應的關系。比如,加法指令00000011寫成匯編語言就是 ADD。只要還原成二進制,匯編語言就可以被 CPU 直接執行,所以它是最底層的低級語言。

二、來歷最早的時候,編寫程序就是手寫二進制指令,然后通過各種開關輸入計算機,比如要做加法了,就按一下加法開關。后來,發明了紙帶打孔機,通過在紙帶上打孔,將二進制指令自動輸入計算機。

為了解決二進制指令的可讀性問題,工程師將那些指令寫成了八進制。二進制轉八進制是輕而易舉的,但是八進制的可讀性也不行。很自然地,最后還是用文字表達,加法指令寫成 ADD。內存地址也不再直接引用,而是用標簽表示。

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

每一種 CPU 的機器指令都是不一樣的,因此對應的匯編語言也不一樣。本文介紹的是目前最常見的 x86 匯編語言,即 Intel 公司的 CPU 使用的那一種。

三、寄存器學習匯編語言,首先必須了解兩個知識點:寄存器和內存模型。

先來看寄存器。CPU 本身只負責運算,不負責儲存數據。數據一般都儲存在內存之中,CPU 要用的時候就去內存讀寫數據。但是,CPU 的運算速度遠高于內存的讀寫速度,為了避免被拖慢,CPU 都自帶一級緩存和二級緩存。基本上,CPU 緩存可以看作是讀寫速度較快的內存。

但是,CPU 緩存還是不夠快,另外數據在緩存里面的地址是不固定的,CPU 每次讀寫都要尋址也會拖慢速度。因此,除了緩存之外,CPU 還自帶了寄存器(register),用來儲存最常用的數據。

也就是說,那些最頻繁讀寫的數據(比如循環變量),都會放在寄存器里面,CPU 優先讀寫寄存器,再由寄存器跟內存交換數據。

寄存器不依靠地址區分數據,而依靠名稱。每一個寄存器都有自己的名稱,我們告訴 CPU 去具體的哪一個寄存器拿數據,這樣的速度是最快的。有人比喻寄存器是 CPU 的零級緩存。

四、寄存器的種類早期的 x86 CPU 只有8個寄存器,而且每個都有不同的用途。現在的寄存器已經有100多個了,都變成通用寄存器,不特別指定用途了,但是早期寄存器的名字都被保存了下來。

EAX

EBX

ECX

EDX

EDI

ESI

EBP

ESP

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

我們常常看到 32位 CPU、64位 CPU 這樣的名稱,其實指的就是寄存器的大小。32 位 CPU 的寄存器大小就是4個字節。

五、內存模型:Heap寄存器只能存放很少量的數據,大多數時候,CPU 要指揮寄存器,直接跟內存交換數據。所以,除了寄存器,還必須了解內存怎么儲存數據。

程序運行的時候,操作系統會給它分配一段內存,用來儲存程序和運行產生的數據。這段內存有起始地址和結束地址,比如從0x1000到0x8000,起始地址是較小的那個地址,結束地址是較大的那個地址。

程序運行過程中,對于動態的內存占用請求(比如新建對象,或者使用malloc命令),系統就會從預先分配好的那段內存之中,劃出一部分給用戶,具體規則是從起始地址開始劃分(實際上,起始地址會有一段靜態數據,這里忽略)。

舉例來說,用戶要求得到10個字節內存,那么從起始地址0x1000開始給他分配,一直分配到地址0x100A,如果再要求得到22個字節,那么就分配到0x1020。

這種因為用戶主動請求而劃分出來的內存區域,叫做 Heap(堆)。它由起始地址開始,從低位(地址)向高位(地址)增長。Heap 的一個重要特點就是不會自動消失,必須手動釋放,或者由垃圾回收機制來回收。

六、內存模型:Stack除了 Heap 以外,其他的內存占用叫做 Stack(棧)。簡單說,Stack 是由于函數運行而臨時占用的內存區域。

請看下面的例子。

int main() {

int a = 2;

int b = 3;

}

上面代碼中,系統開始執行main函數時,會為它在內存里面建立一個幀(frame),所有main的內部變量(比如a和b)都保存在這個幀里面。main函數執行結束后,該幀就會被回收,釋放所有的內部變量,不再占用空間。

如果函數內部調用了其他函數,會發生什么情況?

int main() {

int a = 2;

int b = 3;

return add_a_and_b(a, b);

}

上面代碼中,main函數內部調用了add_a_and_b函數。執行到這一行的時候,系統也會為add_a_and_b新建一個幀,用來儲存它的內部變量。也就是說,此時同時存在兩個幀:main和add_a_and_b。一般來說,調用棧有多少層,就有多少幀。

等到add_a_and_b運行結束,它的幀就會被回收,系統會回到函數main剛才中斷執行的地方,繼續往下執行。通過這種機制,就實現了函數的層層調用,并且每一層都能使用自己的本地變量。

所有的幀都存放在 Stack,由于幀是一層層疊加的,所以 Stack 叫做棧。生成新的幀,叫做“入棧”,英文是 push;棧的回收叫做“出棧”,英文是 pop。

Stack 的特點就是,最晚入棧的幀最早出棧(因為最內層的函數調用,最先結束運行),這就叫做“后進先出”的數據結構。每一次函數執行結束,就自動釋放一個幀,所有函數執行結束,整個 Stack 就都釋放了。

Stack 是由內存區域的結束地址開始,從高位(地址)向低位(地址)分配。比如,內存區域的結束地址是0x8000,第一幀假定是16字節,那么下一次分配的地址就會從0x7FF0開始;第二幀假定需要64字節,那么地址就會移動到0x7FB0。

七、CPU 指令7.1 一個實例

了解寄存器和內存模型以后,就可以來看匯編語言到底是什么了。下面是一個簡單的程序example.c。

int add_a_and_b(int a, int b) {

return a + b;

}

int main() {

return add_a_and_b(2, 3);

}

gcc 將這個程序轉成匯編語言。

$ gcc -S example.c

上面的命令執行以后,會生成一個文本文件example.s,里面就是匯編語言,包含了幾十行指令。這么說吧,一個高級語言的簡單操作,底層可能由幾個,甚至幾十個 CPU 指令構成。CPU 依次執行這些指令,完成這一步操作。

example.s經過簡化以后,大概是下面的樣子。

_add_a_and_b:

push %ebx

mov %eax, [%esp+8]

mov %ebx, [%esp+12]

add %eax, %ebx

pop %ebx

ret

_main:

push 3

push 2

call _add_a_and_b

add %esp, 8

ret

可以看到,原程序的兩個函數add_a_and_b和main,對應兩個標簽_add_a_and_b和_main。每個標簽里面是該函數所轉成的 CPU 運行流程。

每一行就是 CPU 執行的一次操作。它又分成兩部分,就以其中一行為例。

push %ebx

這一行里面,push是 CPU 指令,%ebx是該指令要用到的運算子。一個 CPU 指令可以有零個到多個運算子。

下面我就一行一行講解這個匯編程序,建議讀者最好把這個程序,在另一個窗口拷貝一份,省得閱讀的時候再把頁面滾動上來。

7.2 push 指令

根據約定,程序從_main標簽開始執行,這時會在 Stack 上為main建立一個幀,并將 Stack 所指向的地址,寫入 ESP 寄存器。后面如果有數據要寫入main這個幀,就會寫在 ESP 寄存器所保存的地址。

然后,開始執行第一行代碼。

push 3

push指令用于將運算子放入 Stack,這里就是將3寫入main這個幀。

雖然看上去很簡單,push指令其實有一個前置操作。它會先取出 ESP 寄存器里面的地址,將其減去4個字節,然后將新地址寫入 ESP 寄存器。使用減法是因為 Stack 從高位向低位發展,4個字節則是因為3的類型是int,占用4個字節。得到新地址以后, 3 就會寫入這個地址開始的四個字節。

push 2

第二行也是一樣,push指令將2寫入main這個幀,位置緊貼著前面寫入的3。這時,ESP 寄存器會再減去 4個字節(累計減去8)。

7.3 call 指令

第三行的call指令用來調用函數。

call _add_a_and_b

上面的代碼表示調用add_a_and_b函數。這時,程序就會去找_add_a_and_b標簽,并為該函數建立一個新的幀。

下面就開始執行_add_a_and_b的代碼。

push %ebx

這一行表示將 EBX 寄存器里面的值,寫入_add_a_and_b這個幀。這是因為后面要用到這個寄存器,就先把里面的值取出來,用完后再寫回去。

這時,push指令會再將 ESP 寄存器里面的地址減去4個字節(累計減去12)。

7.4 mov 指令

mov指令用于將一個值寫入某個寄存器。

mov %eax, [%esp+8]

這一行代碼表示,先將 ESP 寄存器里面的地址加上8個字節,得到一個新的地址,然后按照這個地址在 Stack 取出數據。根據前面的步驟,可以推算出這里取出的是2,再將2寫入 EAX 寄存器。

下一行代碼也是干同樣的事情。

mov %ebx, [%esp+12]

上面的代碼將 ESP 寄存器的值加12個字節,再按照這個地址在 Stack 取出數據,這次取出的是3,將其寫入 EBX 寄存器。

7.5 add 指令

add指令用于將兩個運算子相加,并將結果寫入第一個運算子。

add %eax, %ebx

上面的代碼將 EAX 寄存器的值(即2)加上 EBX 寄存器的值(即3),得到結果5,再將這個結果寫入第一個運算子 EAX 寄存器。

7.6 pop 指令

pop指令用于取出 Stack 最近一個寫入的值(即最低位地址的值),并將這個值寫入運算子指定的位置。

pop %ebx

上面的代碼表示,取出 Stack 最近寫入的值(即 EBX 寄存器的原始值),再將這個值寫回 EBX 寄存器(因為加法已經做完了,EBX 寄存器用不到了)。

注意,pop指令還會將 ESP 寄存器里面的地址加4,即回收4個字節。

7.7 ret 指令

ret指令用于終止當前函數的執行,將運行權交還給上層函數。也就是,當前函數的幀將被回收。

ret

可以看到,該指令沒有運算子。

隨著add_a_and_b函數終止執行,系統就回到剛才main函數中斷的地方,繼續往下執行。

add %esp, 8

上面的代碼表示,將 ESP 寄存器里面的地址,手動加上8個字節,再寫回 ESP 寄存器。這是因為 ESP 寄存器的是 Stack 的寫入開始地址,前面的pop操作已經回收了4個字節,這里再回收8個字節,等于全部回收。

ret

最后,main函數運行結束,ret指令退出程序執行。

看完這篇文章,你對匯編語言有什么了解了嗎,看嘛,匯編也不難~

原文鏈接:

http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10873

    瀏覽量

    212038
  • 編程
    +關注

    關注

    88

    文章

    3620

    瀏覽量

    93785
  • 編譯器
    +關注

    關注

    1

    文章

    1634

    瀏覽量

    49160
  • 儲存
    +關注

    關注

    3

    文章

    201

    瀏覽量

    22392

原文標題:計算機怎么識別你寫的代碼?

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    量子計算機與普通計算機工作原理的區別

    ? 本文介紹了量子計算機與普通計算機工作原理的區別。 量子計算是一個新興的研究領域,科學家們利用量子力學,制造出具有革命性能力的計算機。雖然現在的量子
    的頭像 發表于 11-24 11:00 ?339次閱讀
    量子<b class='flag-5'>計算機</b>與普通<b class='flag-5'>計算機</b>工作原理的區別

    ROM對計算機性能的影響

    是一種非易失性存儲器,即使在斷電的情況下也能保持數據不丟失。它通常用于存儲固件,這些固件是計算機啟動和運行操作系統所必需的。ROM的內容在制造過程中被寫入,并且通常不能被用戶更改。 ROM的類型 PROM(可編程ROM) :用戶可以通過特殊的編程設備
    的頭像 發表于 11-04 10:31 ?370次閱讀

    晶體管計算機和電子管計算機有什么區別

    晶體管計算機和電子管計算機作為計算機發展史上的兩個重要階段,它們在多個方面存在顯著的區別。以下是對這兩類計算機在硬件、性能、應用以及技術發展等方面區別的詳細闡述。
    的頭像 發表于 08-23 15:28 ?1846次閱讀

    計算機視覺的工作原理和應用

    計算機視覺(Computer Vision,簡稱CV)是一門跨學科的研究領域,它利用計算機和數學算法來模擬人類視覺系統對圖像和視頻進行識別、理解、分析和處理。其核心目標在于使計算機能夠
    的頭像 發表于 07-10 18:24 ?2055次閱讀

    計算機視覺與人工智能的關系是什么

    引言 計算機視覺是一門研究如何使計算機能夠理解和解釋視覺信息的學科。它涉及到圖像處理、模式識別、機器學習等多個領域的知識。人工智能則是研究如何使計算機具有智能行為的學科,包括感知、學習
    的頭像 發表于 07-09 09:25 ?670次閱讀

    計算機視覺在人工智能領域有哪些主要應用?

    計算機視覺是人工智能領域的一個重要分支,它主要研究如何讓計算機能夠像人類一樣理解和處理圖像和視頻數據。計算機視覺技術在許多領域都有廣泛的應用,以下是一些主要的應用領域: 圖像識別與分類
    的頭像 發表于 07-09 09:14 ?1435次閱讀

    計算機視覺屬于人工智能嗎

    屬于,計算機視覺是人工智能領域的一個重要分支。 引言 計算機視覺是一門研究如何使計算機具有視覺能力的學科,它涉及到圖像處理、模式識別、機器學習等多個領域。
    的頭像 發表于 07-09 09:11 ?1332次閱讀

    工業計算機與普通計算機的區別

    在信息化和自動化日益發展的今天,計算機已經成為了我們日常生活和工作中不可或缺的工具。然而,在計算機領域中,工業計算機和普通計算機雖然都具備基本的計算
    的頭像 發表于 06-06 16:45 ?1444次閱讀

    【量子計算機重構未來 | 閱讀體驗】+量子計算機的原理究竟是什么以及有哪些應用

    本書內容從目錄可以看出本書主要是兩部分內容,一部分介紹量子計算機原理,一部分介紹其應用。 其實個人也是抱著對這兩個問題的興趣來看的。 究竟什么是量子計算機相信很多讀者都是抱著這個疑問
    發表于 03-11 12:50

    【量子計算機重構未來 | 閱讀體驗】+ 初識量子計算機

    欣喜收到《量子計算機——重構未來》一書,感謝電子發燒友論壇提供了一個讓我了解量子計算機的機會! 自己對電子計算機有點了解,但對量子計算機真是一無所知,只是聽說過量子糾纏、超快的運算速
    發表于 03-05 17:37

    計算機視覺的十大算法

    隨著科技的不斷發展,計算機視覺領域也取得了長足的進步。本文將介紹計算機視覺領域的十大算法,包括它們的基本原理、應用場景和優缺點。這些算法在圖像處理、目標檢測、人臉識別等領域有著廣泛的應用,對
    的頭像 發表于 02-19 13:26 ?1255次閱讀
    <b class='flag-5'>計算機</b>視覺的十大算法

    量子計算機的未來

    了解量子計算機對于工業生產和產品研發的使用
    發表于 02-01 15:30

    量子計算機 未來希望

    自己從事語音識別產品設計開發,而量子技術和量子計算機必將在自然語言處理方面實現重大突破,想通過此書學習量子計算技術,儲備知識,謝謝!
    發表于 02-01 12:51

    微機原理和計算機組成原理的區別

    微機原理和計算機組成原理是計算機科學中兩個重要的主題,它們雖然有一定的關聯,但也存在一些區別。本文將詳細闡述微機原理和計算機組成原理的區別,并從不同的角度對它們進行分析比較。 首先,我們從定義的角度
    的頭像 發表于 01-14 14:56 ?3465次閱讀

    計算機視覺:AI如何識別與理解圖像

    計算機視覺是人工智能領域的一個重要分支,它致力于讓機器能夠像人類一樣理解和解釋圖像。隨著深度學習和神經網絡的發展,人們對于如何讓AI識別和理解圖像產生了濃厚的興趣。本文將探討計算機視覺中AI如何進
    的頭像 發表于 01-12 08:27 ?1472次閱讀
    <b class='flag-5'>計算機</b>視覺:AI如何<b class='flag-5'>識別</b>與理解圖像
    主站蜘蛛池模板: 国产手机免费视频| 99热久久久久久久免费观看| 国产视频三区| 久草视频资源在线| 黄色美女网站免费看| 国产福利乳摇在线播放| 操你啦网站| 巨大欧美黑人xxxxbbbb| 免费 的黄色| 日本天天色| 亚洲国产人成在线观看| 91日本视频| 国产精品免费看久久久久| 国产香蕉在线精彩视频| 色视频亚洲| 成年啪啪网站免费播放看| 夜夜五月天| 老色歌uuu26| 黄色在线观看网址| 国产成人乱码一区二区三区| 午夜在线观看完整高清免费| 最新地址四虎www4hutv| 五月亭亭六月丁香| 日本不卡免费新一区二区三区| 久久青草91线频免费观看| www.a级片| www九色| 午夜合集| 天天爽夜夜爽人人爽曰喷水| 欧美高h| 中文字幕一二三四区2021| 精品免费视在线观看| 日本不卡在线视频高清免费| 亚洲精品黄色| 女人被狂躁视频免费网站| 欧美午夜在线视频| 琪琪see色原网一区二区| 黄色的视频免费看| 天天综合天天色| 五月激情视频| 91国在线啪精品一区|