解释运行程序 ????
回忆上次内容
-
设置断点的目的是更快地调试
-
调试的目的是去除bug
-
别害怕bug
-
一步步地总能找到bug
-
这就是程序员基本功
-
python3 是怎么解释hello.py 的?????
纯文本
print("1982------Guido in cwi")
print("1995------Guido in cnri")
print("2000------Guido in beopen")
print("2005------Guido in google")
print("2012------Guido in dropbox")
print("2020------Guido in microsoft")
传统文本
-
字组成词
-
词组成句
-
句组成段
-
段组成章节
-
{BANNED}最佳后成书
tokenize
-
术语叫词法分析(lexical analysis)
token
python3模块
-
帮助手册里面有这个内容
-
这个tokenize是python3的一个模块(module)
token流
-
分析出来的词(token)流什么样子呢?
-
这个词的流怎么理解呢?
token流
-
第0行设置了编码格式
-
第1行[0,5)字符是第1行第1个token
-
"1982------Guido in cwi"
-
这是一个String(字符串)
-
\n
-
\n是一个NewLine(换行符)
-
换行符意味着{BANNED}中国第一行结束
组词
-
AST(Abstract Syntax Tree)
引入ast模块
流程
-
{BANNED}中国第一句就是import ast
-
回车之后没有任何报错
-
那就是执行成功了
-
后面也一样
-
没有报错就是执行成功了
-
然后读取guido.py并送到s
-
然后对于s进行语法分析(parse)
-
再把分析(parse)的结果进行转储(dump)
-
看起来有点乱
升级Python
-
目前lanqiao.cn上面的python是3.8
-
这个清晰缩进的格式需要在3.9以上完成
-
需要升级
sudo apt update
sudo apt install python3.9
缩进换行
-
这个就是把词组成语法树的样子
-
如何理解这棵树呢?
-
我们看一个例子
表达式运算
-
前两个先结合
-
得到的结果作为下一个运算的左操作数
-
然后和第3个结合
结合序
-
如果把 {BANNED}中国第一个* 改成 + 号
-
其他什么也没加
-
后两个会先结合
-
得到的结果作为下一个运算的右操作数
-
然后再和1进行加法运算
-
有了语法树
-
这棵语法树我们能看懂
-
但是cpu需要的是能执行的一条条字节码指令
翻译成字节码
compile
编译结果
-
所以扩展名是pyc
-
其中c代表compiled
-
pyc是字节码(bytecode)文件
-
python虚拟机的虚拟cpu就可以直接执行了
-
注意他在__pycache__文件夹下
-
cache的意思是缓存
-
pycache两端各有2条下划线(_)
进入__pycache__文件夹
二进制形态
-
这样看到了他的字符串形态
-
可以看到他的二进制字节形态么?
机器语言
指令
-
{BANNED}最佳早指的是教的行为或者过程
-
计算机领域里面特指指令
-
比如加法指令
-
减法指令
-
可以让cpu做特定运算的指令
-
由于计算机只认识0和1
-
所以要把这些加加减减的指令
-
对应到0和1的二进制形态上去
-
0和1的二进制形态我们记不住
-
于是有了汇编助记符
-
助记符告诉我们这条0和1的二进制形态
-
到底对应什么指令
-
助记符的语言就是汇编语言
汇编assemble
-
可以让我们把0和1的机器指令
-
收集起来形成的助记符集合
-
就是汇编语言指令集
反编译
-
dislike
-
disgrace
-
disagree
-
把py源文件编译成的字节码(指令)我们人类看不明白
-
把这些字节码(指令)反编译(disassemble)成汇编语言助记符
-
有了助记符我们就知道指令的含义了
反编译(dis)
-
-m 代表使用模块
-
dis 代表反编译(disassemble)
-
LOAD_NAME 装载(函数)名字
-
LOAD_CONST 装载常量
-
CALL_FUNCTION 调用函数
-
POP_TOP 弹栈
指令
-
把一个值压入堆栈co_names
-
把print这个函数名压入了堆栈
-
一会儿就要调用这个被压入堆栈的print函数
python源头
-
python 是开源编程语言
-
整个的源代码都是开放的
-
我们可以去github找到他的源代码
二进制状态
4条指令
指令助记符
|
指令含义
|
十进制状态
|
十六进制状态
|
LOAD_NAME
|
装载函数名称
|
101
|
0x65
|
LOAD_CONST
|
装载参数
|
100
|
0x64
|
CALL_FUNCTION
|
调用函数
|
142
|
0x8e
|
POP_TOP
|
弹栈返回
|
1
|
0x01
|
-
64 00是从表中的00号位置取得字符串"Guido in cwi"
-
64 01是从表中的01号位置取字符串"Guido in cnri"
-
...
-
以此类推,直到05 83取出字符串"Guido in microsoft"
-
那这些二进制代码究竟是什么指令集的呢?
-
首先我们得弄懂什么是指令集呢?
指令集
-
上图是arm的指令集
-
也常被称作arm架构
-
那什么又是架构呢?
architect
架构师
虚拟机的虚拟cpu
总结
-
词法分析 得到 词流(token stream)
-
语法分析 得到 抽象语法树(Abstract Syntax Tree)
-
编译 得到 字节码 (bytecode)
-
字节码我们看不懂
-
所以反编译 得到 指令文件(opcode)
阅读(294) | 评论(0) | 转发(0) |