MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计.
#include <stdint.h> // 标准整数类型头文件
#include <stdio.h> // 标准输入输出头文件
#include <assert.h> // 断言头文件
#include <string.h> // 字符串操作头文件
#include "py/mpconfig.h" // MicroPython 配置头文件
// 此文件中所有内容的包装器
#if MICROPY_EMIT_X86
#include "py/asmx86.h" // MicroPython X86 汇编头文件
/* 所有偏移量以 4 字节为单位进行测量 */
#define WORD_SIZE (4)
#define OPCODE_NOP (0x90) // 无操作指令
#define OPCODE_PUSH_R32 (0x50) // 推送 32 位寄存器到栈顶指令
// #define OPCODE_PUSH_I32 (0x68) // 推送 32 位立即数到栈顶指令
// #define OPCODE_PUSH_M32 (0xff) // 推送 32 位内存值到栈顶指令
#define OPCODE_POP_R32 (0x58) // 弹出栈顶值到 32 位寄存器指令
#define OPCODE_RET (0xc3) // 返回指令
// #define OPCODE_MOV_I8_TO_R8 (0xb0) // 将 8 位立即数移动到 8 位寄存器指令
#define OPCODE_MOV_I32_TO_R32 (0xb8) // 将 32 位立即数移动到 32 位寄存器指令
// #define OPCODE_MOV_I32_TO_RM32 (0xc7) // 将 32 位立即数移动到 32 位内存指令
#define OPCODE_MOV_R8_TO_RM8 (0x88) // 将 8 位寄存器值移动到 8 位内存指令
#define OPCODE_MOV_R32_TO_RM32 (0x89) // 将 32 位寄存器值移动到 32 位内存指令
#define OPCODE_MOV_RM32_TO_R32 (0x8b) // 将 32 位内存值移动到 32 位寄存器指令
#define OPCODE_MOVZX_RM8_TO_R32 (0xb6) // 将 8 位内存值零扩展到 32 位寄存器指令
#define OPCODE_MOVZX_RM16_TO_R32 (0xb7) // 将 16 位内存值零扩展到 32 位寄存器指令
#define OPCODE_LEA_MEM_TO_R32 (0x8d) // 将内存地址加载到 32 位寄存器指令
#define OPCODE_NOT_RM32 (0xf7) // 对 32 位内存值进行逻辑非指令
#define OPCODE_NEG_RM32 (0xf7) // 对 32 位内存值进行取反指令
#define OPCODE_AND_R32_TO_RM32 (0x21) // 对 32 位内存值和 32 位寄存器值进行逻辑与指令
#define OPCODE_OR_R32_TO_RM32 (0x09) // 对 32 位内存值和 32 位寄存器值进行逻辑或指令
#define OPCODE_XOR_R32_TO_RM32 (0x31) // 对 32 位内存值和 32 位寄存器值进行逻辑异或指令
#define OPCODE_ADD_R32_TO_RM32 (0x01) // 将 32 位寄存器值加到 32 位内存值上指令
#define OPCODE_ADD_I32_TO_RM32 (0x81) // 将 32 位立即数加到 32 位内存值上指令
#define OPCODE_ADD_I8_TO_RM32 (0x83) // 将 8 位立即数加到 32 位内存值上指令
#define OPCODE_SUB_R32_FROM_RM32 (0x29) // 从 32 位内存值中减去 32 位寄存器值指令
#define OPCODE_SUB_I32_FROM_RM32 (0x81) // 从 32 位内存值中减去 32 位立即数指令
#define OPCODE_SUB_I8_FROM_RM32 (0x83) // 从 32 位内存值中减去 8 位立即数指令
// #define OPCODE_SHL_RM32_BY_I8 (0xc1) // 将 32 位内存值左移指定的 8 位立即数指令
// #define OPCODE_SHR_RM32_BY_I8 (0xc1) // 将 32 位内存值右移指定的 8 位立即数指令
// #define OPCODE_SAR_RM32_BY_I8 (0xc1) // 将 32 位内存值算术右移指定的 8 位立即数指令
#define OPCODE_SHL_RM32_CL (0xd3) // 将 32 位内存值左移 CL 寄存器指定的位数指令
#define OPCODE_SHR_RM32_CL (0xd3) // 将 32 位内存值右移 CL 寄存器指定的位数指令
#define OPCODE_SAR_RM32_CL (0xd3) // 将 32 位内存值算术右移 CL 寄存器指定的位数指令
// #define OPCODE_CMP_I32_WITH_RM32 (0x81) // 将 32 位内存值和 32 位立即数进行比较指令
// #define OPCODE_CMP_I8_WITH_RM32 (0x83) // 将 8 位内存值和 32 位寄存器进行比较指令
#define OPCODE_CMP_R32_WITH_RM32 (0x39) // 将 32 位寄存器值和 32 位内存值进行比较指令
// #define OPCODE_CMP_RM32_WITH_R32 (0x3b) // 将 32 位内存值和 32 位寄存器进行比较指令
#define OPCODE_TEST_R8_WITH_RM8 (0x84) // 测试 8 位寄存器值和 8 位内存值指令
#define OPCODE_TEST_R32_WITH_RM32 (0x85) // 测试 32 位寄存器值和 32 位内存值指令
#define OPCODE_JMP_REL8 (0xeb) // 相对 8 位跳转指令
#define OPCODE_JMP_REL32 (0xe9) // 相对 32 位跳转指令
#define OPCODE_JMP_RM32 (0xff) // 跳转到 32 位内存指令
#define OPCODE_JCC_REL8 (0x70) // 条件跳转相对 8 位指令
#define OPCODE_JCC_REL32_A (0x0f) // 条件跳转相对 32 位指令 A
#define OPCODE_JCC_REL32_B (0x80) // 条件跳转相对 32 位指令 B
#define OPCODE_SETCC_RM8_A (0x0f) // 设置条件代码到 8 位内存 A
#define OPCODE_SETCC_RM8_B (0x90) // 设置条件代码到 8 位内存 B
#define OPCODE_CALL_REL32 (0xe8) // 相对 32 位调用指令
#define OPCODE_CALL_RM32 (0xff) // 调用 32 位内存指令
#define OPCODE_LEAVE (0xc9) // 退出指令
#define MODRM_R32(x) ((x) << 3) // 32 位寄存器的 MODRM 编码
#define MODRM_RM_DISP0 (0x00) // 内存地址偏移量为 0 的 MODRM 编码
#define MODRM_RM_DISP8 (0x40) // 内存地址偏移量为 8 位有符号数的 MODRM 编码
#define MODRM_RM_DISP32 (0x80) // 内存地址偏移量为 32 位有符号数的 MODRM 编码
#define MODRM_RM_REG (0xc0) // 内存地址为寄存器的 MODRM 编码
#define MODRM_RM_R32(x) (x) // 32 位寄存器的 MODRM 编码
#define OP_SIZE_PREFIX (0x66) // 操作数大小前缀
#define IMM32_L0(x) ((x) & 0xff) // 立即数的低 8 位
#define IMM32_L1(x) (((x) >> 8) & 0xff) // 立即数的次低 8 位
#define IMM32_L2(x) (((x) >> 16) & 0xff) // 立即数的次高 8 位
#define IMM32_L3(x) (((x) >> 24) & 0xff) // 立即数的高 8 位
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) // 判断一个值是否适合 8 位有符号数
static void asm_x86_write_byte_1(asm_x86_t *as, byte b1) {
byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // 获取当前位置的指针以写入一个字节
if (c != NULL) {
c[0] = b1;
}
}
static void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) {
byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2); // 获取当前位置的指针以写入两个字节
if (c != NULL) {
c[0] = b1;
c[1] = b2;
}
}
static void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) {
byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3); // 获取当前位置的指针以写入三个字节
if (c != NULL) {
c[0] = b1;
c[1] = b2;
c[2] = b3;
}
}
static void asm_x86_write_word32(asm_x86_t *as, int w32) {
byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4); // 获取当前位置的指针以写入四个字节
if (c != NULL) {
c[0] = IMM32_L0(w32);
c[1] = IMM32_L1(w32);
c[2] = IMM32_L2(w32);
c[3] = IMM32_L3(w32);
}
}
static void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset