最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

[oeasy]python0011 - python虛擬機的本質(zhì)_cpu架構(gòu)_二進制字節(jié)碼_匯編語言

2022-10-27 09:17 作者:oeasy  | 我要投稿

程序本質(zhì)

回憶上次內(nèi)容

  • 我們把python源文件

    • 詞法分析 得到 詞流(token stream)

    • 語法分析 得到 抽象語法樹(Abstract Syntax Tree)

    • 編譯 得到 字節(jié)碼 (bytecode)

    • 字節(jié)碼我們看不懂

    • 所以反編譯 得到 指令文件(opcode)

  • 指令文件是基于python虛擬機的虛擬cpu的指令集

  • 什么是python虛擬機呢???

  • 在了解虛擬cpu之前

  • 我們先看看真實的cpu

真實的cpu

  • 無論手機還是計算機

    • 最核心器件的器件就是cpu

  • 這個東西是個實實在在存在的實體

  • 我們所說的python虛擬機能看到么?

  • 就是用來運行py文件的

python3 到底是個啥?

which python3 ll /usr/bin/python3

  • 這個 python3

    • 是一個符號鏈接文件

    • 只有9字節(jié)

    • 他指向 python3.8

  • python3.8

    • 也在 /usr/bin 里面

  • 就是/usr/bin/python3.8

  • python3.8是一個5.3M的文件

  • 可以看得見

  • 可以直接運行這個phthon3.8嗎?

直接運行

/usr/bin/python3.8

  • python3.8 就在硬盤里呆著

    • usr 是 unix software resource

    • bin 是二進制 binary

    • python3.8 是這個文件的名稱

    • 位置就在/usr/bin/python3.8

  • 在運行命令的時候

    • 把這個文件從硬盤裝載到內(nèi)存

    • 然后用 cpu 開始逐行執(zhí)行文件中的0101指令

  • 可以把他復(fù)制到shiyanlou用戶的宿主文件夾下嗎?

復(fù)制

  • 復(fù)制到shiyanlou下

  • 再觀察

#把/usr/bin/python3這個py文件的解釋器拷貝到~(當(dāng)前用戶文件夾)#cp的意思是copycp /usr/bin/python3 ~#確認python3已經(jīng)拷到~(當(dāng)前用戶文件夾)#ls的意思是listls ~/python3.8#查看python3文件細節(jié)ls -lah ~/python3.8

  • python3 指向的 python3.8 只有 5.3M

    • 這個可執(zhí)行文件怎么這么小?

    • 5.3M 這也就是一張照片的大小

  • 以前的 Python3.5 只有 4.3M

    • 更小

  • 目前這 5.3M 的 Python3 里面到底有什么呢???

研究 python3

#用vi打開這個剛拷貝過來的python3vi ~/python3.8

  • 這個樣子看起來

    • 全是亂碼

    • 完全看不懂啊

  • 這個東西我們確實看不懂

  • 但是有人能看懂

  • 誰呢?

cpu

  • cpu能看懂!?。?/p>

  • 這些我們看不懂的亂碼

    • cpu能看懂

    • 這是屬于cpu的機器語言

    • 這就是cpu的一條條的機器指令(instruction)

  • 機器指令碼都是二進制形式的

  • 我們嘗試把python3.8轉(zhuǎn)化為字節(jié)表現(xiàn)形式

以字節(jié)形式觀察python3.8

vi ~/python3.8

  • 用vim打開~/python3.8

  • :

    • 進入命令行模式

  • :%!xxd我們可以看到這個文件的二進制形態(tài)

    • %是指的對于所有行的范圍

    • !是執(zhí)行外部命令

    • xxd指的是轉(zhuǎn)化為 16 進制形式

  • 什么是xxd命令呢?

xxd

  • xxd 可以查看文件的二進制形態(tài)

    • dump的本意是(傾倒垃圾)

    • 這里指的是轉(zhuǎn)儲

    • 把文件轉(zhuǎn)儲為16進制形式匯編代碼形式

  • :xxd –r 可以還原回去 ??

    • :%!xxd 轉(zhuǎn)成字節(jié)形態(tài)

    • :%!xxd –r 轉(zhuǎn)回文本形態(tài)

  • 反復(fù)橫跳...

另存為python3.8hex

  • 一行是(16)10 進制 ?個字節(jié)

  • G到最后一行

  • 總共有 343148 行

  • 這就是 真正的機器語言??

    • cpu能執(zhí)行的東西

    • 真真切切看到了的

    • 真的存在硬盤上 01010 的二進制可執(zhí)行指令??!

    • 這些指令執(zhí)行出來就是我們的游樂場?。?!

    • 或者說是我們的python虛擬機

  • 可是這個指令我們看不懂怎么辦???

  • 先把他另存出來

    • :w python3.8hex

    • 把當(dāng)前緩存(buffer)另存(write)為

    • python3.8hex

  • 對python3.8強制退出

    • :q!

    • 不保存修改強制退出

  • python3.8hex就是我們要的機器語言的字節(jié)形態(tài)

  • 可是這字節(jié)形態(tài)我們看不懂啊

匯編語言助記符

#先把~/python3對應(yīng)的機器語言輸出為匯編指令形式(反匯編)objdump -d python3.8 > python3.8.asm vi python3.8.asm

  • 這次真的可以看懂了

    • 減法(sub)

    • 移動(mov)

    • 這些指令

  • 可以發(fā)現(xiàn)當(dāng)前系統(tǒng)的架構(gòu)(指令集)是x86-64

  • 這些和我們剛才的字節(jié)形態(tài)有關(guān)系嗎?

對比

  • 用vi分窗口分別打開打開python3 和 python3.asm

vi -o python3.8hex python3.8.asm

  • 下圖中上半部分是機器語言

  • 上圖下半部分是機器語言對應(yīng)的匯編指令助記符

  • ctrl+j、ctrl+k可以上下切換

  • 我們來試著找找

    • python3文件中

    • 機器語言的0101和cpu的匯編指令的對應(yīng)關(guān)系??

找到了

  • 先跳過下面窗格的第8行

    • endbr64 意味著 64位結(jié)束分支

    • 下面的sub執(zhí)行的是減法

  • 下面窗格的 第9行

    • /48 83 找到上下的對應(yīng)關(guān)系

    • 也就是第一條執(zhí)行的匯編指令減法(sub)

    • 匯編指令是計算機 cpu 機器指令的助記符

查找對應(yīng)關(guān)系

  • 423000 就是初始化(init)的 cpu 開始執(zhí)行指令的地址

  • 我們在上面查找48 83 有沒有對應(yīng)的字節(jié)

    • /4883 ec08 488b...

    • 在上面的窗格中

    • 搜索這些字節(jié)形態(tài)

  • 好像找到了對應(yīng)關(guān)系

  • 具體怎么對應(yīng)的呢?

  • 這臺計算機用的是什么指令集呢?

  • 什么是指令集來著?

指令集

  • 指令集就是指令的集合

  • 指令集也叫計算機的架構(gòu)

  • 不同架構(gòu)的 cpu 有不同的指令集

    • 我們目前的這個瀏覽器里面的系統(tǒng)用的是 x86-64

    • 除此之外 armMIPS、RISC-V 也是常用的指令集

  • 指令助記符和機器語言到底是則怎么對應(yīng)的呢?

回到代碼

  • 代碼會有不同的 section 模塊

    • 入口是 init

    • 作用是初始化initialization

  • 模塊里面是具體的指令

    • 比如第一句 48 83 ec 08

  • 為什么48 83 就可以代表減法

  • 這是誰規(guī)定的呢?

查看指令集

  • 這是cpu架構(gòu)規(guī)定的

    • 首先要明確到當(dāng)前機器cpu的架構(gòu)

    • 反匯編里面說是x86-64

  • 到shell里面驗證一下

  • 當(dāng)前機器所用的架構(gòu)指令集確實是x86_64

  • 這是誰的架構(gòu)呢?

搜索

  • 不會了就去搜索??

  • 去intel官網(wǎng)找指令集

查詢x86_64指令集

  • 找到cpu的手冊

    • https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf

  • 可以找到指令和二進制狀態(tài)之間的關(guān)系么?

    • 先要找到x86-64指令集中 48 83 這條指令

  • 注意上圖中

    • 100B中的B是0或1

    • 100B可以是1000

    • 也可以是1001

  • 這確實是一條減法指令

    • 而且是8位立即數(shù)和寄存器的減法運算

逐步搜索

  • 找起來真的很費勁

    • 48 83 ec 08 對應(yīng) sub $0x8,%rsp

    • 確實是一條減法指令

    • 確實是8位立即數(shù)和寄存器的減法運算

  • 和objdump的結(jié)果是一致的

    • 廢話?。?!??

  • 除了減法指令sub之外

  • 還有什么別的指令呢?

各種cpu指令

  • 指令那可還有很多的

    • 有運算的

    • 有移位的

    • 加減乘除都有

  • 這些指令的集合就是指令集

    • 指令集就是cpu運行的基礎(chǔ)!

  • 這些機器語言的指令不能在別的指令集架構(gòu)上運行么?

移植 port

  • 想在別的指令集架構(gòu)上運行程序

    • 就需要移植(port)

    • 移植(port)指的是從一種指令集移植到另一種指令集

  • 從這個詞的詞源

    • 移植

    • port 港口

    • 可以看出歐美的航海文化基礎(chǔ)

    • 也可以看出我們的農(nóng)耕文化基礎(chǔ)

  • 不移植會如何呢?

不移植

  • 這是playstation2的架構(gòu)圖

    • cpu是mips架構(gòu)的

  • 不移植的話

    • 就是讓x86架構(gòu)的pc

    • 去直接執(zhí)行這些基于mips架構(gòu)的的0101...

  • 就像讓一個意大利泥瓦匠看一份中文寫成的烹飪書來砌墻

    • 雞同鴨講

    • 驢唇不對馬嘴

    • 0101的文件執(zhí)行出來全是亂的

    • 完全不能用

  • 而且不全是軟件的問題

    • 也涉及到硬件等方面

    • 可能某個寄存器在新架構(gòu)中根本就不存在

架構(gòu)師

  • 這個時候架構(gòu)師要解決相當(dāng)多的問題

  • 很不容易的

  • 落實到我們的python3.8游樂場

    • 我們的python3.8就是這樣的一系列的cpu指令

    • 可以解釋py文件的

  • python3.8 又是如何解釋py文件的來著?

python3 執(zhí)行過程

  • 不管是python3這個游樂場

  • 還是hello.py這個python程序

  • 都在我們的硬盤上

  • 先得把文件從硬盤讀到內(nèi)存

python3 執(zhí)行的過程大致是這樣

  • 先把python3.8這個主解釋器加載到內(nèi)存中

    • 然后在x86-64的cpu上執(zhí)行

    • 模擬出一臺python虛擬機

  • 準備開始對py文件解釋執(zhí)行

先編譯

  • 然后把參數(shù) hello.py 這個需要執(zhí)行的程序加載到內(nèi)存

    • 詞法分析 得到 詞流(token stream)

    • 語法分析 得到 抽象語法樹(Abstract Syntax Tree)

    • 編譯 得到 字節(jié)碼 (bytecode)

  • 也就是編譯后的pyc文件

解釋執(zhí)行

  • 不過這個pyc指令文件

    • 是基于python虛擬機的虛擬cpu的指令集的

  • 需要放到模擬好的python虛擬機中

  • 一條條指令進行執(zhí)行

換句話說

  • 簡化版的 hello.py 的執(zhí)行過程是:

    • 給了 python3 一個參數(shù) hello.py

    • 使用 python3 這個解釋器來解釋執(zhí)行 hello.py

    • hello.py中的語句一句句地依次解釋執(zhí)行

  • 全解釋完成后

    • 退出python這個程序

    • 把控制權(quán)交回到shell

  • 這些都是基于解釋器python3.8的

    • 先編譯成python虛擬機的字節(jié)碼

    • 然后用python虛擬機解釋直接執(zhí)行

    • 所謂的解釋器也是

  • 而解釋器(python3)是在不同系統(tǒng)不同架構(gòu)的cpu語言上運行的

    • 那不同的系統(tǒng)、cpu架構(gòu)

    • python都能正確地解釋么?

架構(gòu)的層次

  • 不同架構(gòu)的 cpu 都可以運行 python

    • risc-v

    • arm

    • x64

    • mips

    • 龍芯

  • 不同系統(tǒng)的環(huán)境都可以運行 python

    • win

    • mac

    • linux

    • freebsd

跨架構(gòu)跨平臺原理

  • 由于python3可以運行在不同的cpu架構(gòu)和系統(tǒng)上

    • 所以同樣的py文件被加載之后

    • python程序可以對py文件跨架構(gòu)、跨系統(tǒng)進行解釋執(zhí)行

    • 一次編寫到處運行

  • 不同的架構(gòu)

    • 二進制對應(yīng)的匯編指令都不一樣

    • 怎么能正確解釋執(zhí)行同樣的python程序呢?

跨架構(gòu)跨平臺原理

  • /usr/bin/python3.8 本身是二進制文件

    • 是基于當(dāng)前操作系統(tǒng)當(dāng)前架構(gòu)編譯出來的可執(zhí)行二進制文件

    • 不同的架構(gòu)有不同的編譯器

    • 不同的編譯器編譯出來的python3.8

    • 是不同的二進制指令序列

  • python3.8 構(gòu)建了一個運行時環(huán)境

    • 這個環(huán)境可以解釋讀到的python語句

    • python語句翻譯成系統(tǒng)能讀懂輸入輸出

    • 翻譯成當(dāng)前架構(gòu)能夠執(zhí)行的代碼

  • 然后邊解釋邊執(zhí)行

  • 恭喜您完成了非常燒腦一個實驗!

  • 我們?nèi)タ偨Y(jié)吧?。?!

總結(jié)

  • python3 的程序是一個 5.3M 的可執(zhí)行文件

    • objdump -d ~/python3 > python3.asm

    • python3 里面全都是 cpu 指令

    • 可以執(zhí)行的那種

    • 我們可以把指令對應(yīng)的匯編找到

  • 匯編語句是和當(dāng)前機器架構(gòu)的指令集相關(guān)的

    • uname -a可以查詢指令集

  • 我們執(zhí)行的過程其實就

    • 系統(tǒng)執(zhí)行python3這個可執(zhí)行文件

    • 給了python3一個參數(shù)hello.py

    • python3對于hello.py一句句的解釋執(zhí)行

    • 在顯示器輸出了hello world

    • python3執(zhí)行完畢

    • 把控制權(quán)交回給 shell

  • 這就是我們執(zhí)行hello.py的過程

  • 為什么我們學(xué)編程總是從hello world開始呢???

  • 我們下次再說!??

  • 藍橋->https://www.lanqiao.cn/teacher/3584

  • github->https://github.com/overmind1980/oeasy-python-tutorial

  • gitee->https://gitee.com/overmind1980/oeasypython

  • 視頻->https://www.bilibili.com/video/BV1CU4y1Z7gQ


[oeasy]python0011 - python虛擬機的本質(zhì)_cpu架構(gòu)_二進制字節(jié)碼_匯編語言的評論 (共 條)

分享到微博請遵守國家法律
江川县| 吉安市| 神木县| 鹤庆县| 沈丘县| 特克斯县| 通州区| 浏阳市| 福清市| 汉阴县| 平顶山市| 五台县| 高碑店市| 惠州市| 温泉县| 荃湾区| 安新县| 达孜县| 长沙市| 聂荣县| 莱州市| 封开县| 阜新| 汉沽区| 怀仁县| 微山县| 和龙市| 自贡市| 桓台县| 启东市| 桦川县| 措勤县| 莫力| 内丘县| 星子县| 乐都县| 许昌县| 穆棱市| 大兴区| 虞城县| 密云县|