MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
microPython Python最小内核源码解析
NI-motion运动控制c语言示例代码解析
python编程示例系列 python编程示例系列二
python的Web神器Streamlit
这段代码是一个用于打印MicroPython字节码的调试工具。它定义了一系列宏来解码字节码中的不同部分,如标签、字符串、指针和对象等。然后,它提供了两个主要的函数:mp_bytecode_print
和mp_bytecode_print2
,用于递归地打印整个字节码对象的内容。这对于开发者在开发和调试MicroPython程序时非常有用,因为它可以显示程序的底层操作和流程。代码中的注释详细解释了每个步骤和指令的作用,有助于理解字节码的结构和执行逻辑。
#include <stdio.h>
#include <assert.h>
#include "py/bc0.h"
#include "py/emitglue.h"
#if MICROPY_DEBUG_PRINTERS
// 定义解码无符号整数的宏
#define DECODE_UINT {
\
unum = 0; \
do {
\
unum = (unum << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
}
// 定义解码无符号标签的宏
#define DECODE_ULABEL \
do {
\
if (ip[0] & 0x80) {
\
unum = ((ip[0] & 0x7f) | (ip[1] << 7)); \
ip += 2; \
} else {
\
unum = ip[0]; \
ip += 1; \
} \
} while (0)
// 定义解码有符号标签的宏
#define DECODE_SLABEL \
do {
\
if (ip[0] & 0x80) {
\
unum = ((ip[0] & 0x7f) | (ip[1] << 7)) - 0x4000; \
ip += 2; \
} else {
\
unum = ip[0] - 0x40; \
ip += 1; \
} \
} while (0)
// 定义解码字符串的宏
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
#define DECODE_QSTR \
DECODE_UINT; \
qst = qstr_table[unum]
#else
#define DECODE_QSTR \
DECODE_UINT; \
qst = unum;
#endif
// 定义解码指针的宏
#define DECODE_PTR \
DECODE_UINT; \
unum = (mp_uint_t)(uintptr_t)child_table[unum]
// 定义解码对象的宏
#define DECODE_OBJ \
DECODE_UINT; \
unum = (mp_uint_t)obj_table[unum]
// 打印字节码的函数
void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, size_t fun_data_len, const mp_module_constants_t *cm) {
const byte *ip_start = rc->fun_data; // 指向函数数据的起始地址
const byte *ip = rc->fun_data; // 指向当前处理的字节码
// 解码序言部分
MP_BC_PRELUDE_SIG_DECODE(ip); // 解码函数签名
MP_BC_PRELUDE_SIZE_DECODE(ip); // 解码函数大小
const byte *code_info = ip; // 指向代码信息的地址
// 解码块名称和源文件
qstr block_name = mp_decode_uint(&code_info); // 解码块名称
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
block_name = cm->qstr_table[block_name]; // 获取块名称
qstr source_file = cm->qstr_table[0]; // 获取源文件名称
#else
qstr source_file = cm->source_file; // 直接获取源文件名称
#endif
mp_printf(print, "文件 %s, 代码块 '%s' (描述符: %p, 字节码 @%p %u 字节)\n",
qstr_str(source_file), qstr_str(block_name), rc, ip_start, (unsigned)fun_data_len);
// 打印原始字节码
size_t prelude_size = ip - ip_start + n_info + n_cell; // 计算序言大小
mp_printf(print, "原始字节码 (code_info_size=%u, bytecode_size=%u):\n",
(unsigned)prelude_size, (unsigned)(fun_data_len - prelude_size));
for (size_t i = 0; i < fun_data_len; i++) {
if (i > 0 && i % 16 == 0) {
mp_printf(print, "\n");
}
mp_printf(print, " %02x", ip_start[i]); // 打印字节码
}
mp_printf(print, "\n");
// 打印参数名称
mp_printf(print, "参数名称:");
for (mp_uint_t i = 0; i < n_pos_args + n_kwonly_args; i++) {
qstr qst = mp_decode_uint(&code_info); // 解码参数名称
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
qst = cm->qstr_table[qst]; // 获取参数名称
#endif
mp_printf(print, " %s", qstr_str(qst)); // 打印参数名称
}
mp_printf(print, "\n");
mp_printf(print, "(N_STATE %u)\n", (unsigned)n_state); // 打印状态数量
mp_printf(print, "(N_EXC_STACK %u)\n", (unsigned)n_exc_stack); // 打印异常堆栈数量
// 跳过代码信息
ip += n_info;
const byte *line_info_top = ip; // 指向行号信息的顶部
// 打印闭包变量的初始值