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_X64
#include "py/asmx64.h" // MicroPython x64汇编头文件
/* 所有偏移量以8字节的倍数进行测量 */
#define WORD_SIZE (8)
#define OPCODE_NOP (0x90) // 无操作指令
#define OPCODE_PUSH_R64 (0x50) // 推送64位寄存器到栈顶(+rq)
#define OPCODE_PUSH_I64 (0x68) // 推送64位立即数到栈顶(+i64)
#define OPCODE_PUSH_M64 (0xff) // 推送64位内存到栈顶(/6)
#define OPCODE_POP_R64 (0x58) // 从栈顶弹出64位寄存器(+rq)
#define OPCODE_RET (0xc3) // 返回指令
#define OPCODE_MOV_I8_TO_R8 (0xb0) // 将8位立即数移动到8位寄存器(+rb)
#define OPCODE_MOV_I64_TO_R64 (0xb8) // 将64位立即数移动到64位寄存器(+rq)
#define OPCODE_MOV_I32_TO_RM32 (0xc7) // 将32位立即数移动到32位内存(+i32)
#define OPCODE_MOV_R8_TO_RM8 (0x88) // 将8位寄存器移动到8位内存(/r)
#define OPCODE_MOV_R64_TO_RM64 (0x89) // 将64位寄存器移动到64位内存(/r)
#define OPCODE_MOV_RM64_TO_R64 (0x8b) // 将64位内存移动到64位寄存器(/r)
#define OPCODE_MOVZX_RM8_TO_R64 (0xb6) // 将8位内存零扩展到64位寄存器(0x0f 0xb6/r)
#define OPCODE_MOVZX_RM16_TO_R64 (0xb7) // 将16位内存零扩展到64位寄存器(0x0f 0xb7/r)
#define OPCODE_LEA_MEM_TO_R64 (0x8d) // 将内存地址加载到64位寄存器(/r)
#define OPCODE_NOT_RM64 (0xf7) // 64位内存按位非(/2)
#define OPCODE_NEG_RM64 (0xf7) // 64位内存取反(/3)
#define OPCODE_AND_R64_TO_RM64 (0x21) // 64位寄存器与内存按位与(/r)
#define OPCODE_OR_R64_TO_RM64 (0x09) // 64位寄存器与内存按位或(/r)
#define OPCODE_XOR_R64_TO_RM64 (0x31) // 64位寄存器与内存按位异或(/r)
#define OPCODE_ADD_R64_TO_RM64 (0x01) // 64位寄存器与内存相加(/r)
#define OPCODE_ADD_I32_TO_RM32 (0x81) // 32位内存与32位立即数相加(/0)
#define OPCODE_ADD_I8_TO_RM32 (0x83) // 32位内存与8位立即数相加(/0)
#define OPCODE_SUB_R64_FROM_RM64 (0x29) // 64位寄存器从内存中减去(+r64)
#define OPCODE_SUB_I32_FROM_RM64 (0x81) // 32位内存从64位寄存器中减去(/5)
#define OPCODE_SUB_I8_FROM_RM64 (0x83) // 32位内存从64位寄存器中减去(/5)
// #define OPCODE_SHL_RM32_BY_I8 (0xc1) // 32位内存左移指定位数(/4)
// #define OPCODE_SHR_RM32_BY_I8 (0xc1) // 32位内存右移指定位数(/5)
// #define OPCODE_SAR_RM32_BY_I8 (0xc1) // 32位内存算术右移指定位数(/7)
#define OPCODE_SHL_RM64_CL (0xd3) // 64位内存左移cl指定位数(/4)
#define OPCODE_SHR_RM64_CL (0xd3) // 64位内存右移cl指定位数(/5)
#define OPCODE_SAR_RM64_CL (0xd3) // 64位内存算术右移cl指定位数(/7)
// #define OPCODE_CMP_I32_WITH_RM32 (0x81) // 比较32位内存和32位立即数(/7)
// #define OPCODE_CMP_I8_WITH_RM32 (0x83) // 比较8位内存和32位立即数(/7)
#define OPCODE_CMP_R64_WITH_RM64 (0x39) // 比较64位寄存器和64位内存(/r)
// #define OPCODE_CMP_RM32_WITH_R32 (0x3b)
#define OPCODE_TEST_R8_WITH_RM8 (0x84) // 测试8位寄存器和内存(/r)
#define OPCODE_TEST_R64_WITH_RM64 (0x85) // 测试64位寄存器和内存(/r)
#define OPCODE_JMP_REL8 (0xeb) // 相对8位跳转指令
#define OPCODE_JMP_REL32 (0xe9) // 相对32位跳转指令
#define OPCODE_JMP_RM64 (0xff) // 跳转到64位内存指令(/4)
#define OPCODE_JCC_REL8 (0x70) // 条件跳转8位相对指令(| jcc 类型)
#define OPCODE_JCC_REL32_A (0x0f) // 条件跳转32位相对指令A(+ jcc 类型)
#define OPCODE_JCC_REL32_B (0x80) // 条件跳转32位相对指令B(| jcc 类型)
#define OPCODE_SETCC_RM8_A (0x0f) // 设置条件代码到8位内存A(+ jcc 类型)
#define OPCODE_SETCC_RM8_B (0x90) // 设置条件代码到8位内存B(| jcc 类型, /0)
#define OPCODE_CALL_REL32 (0xe8) // 相对32位调用指令
#define OPCODE_CALL_RM32 (0xff) // 调用64位内存指令(/2)
#define OPCODE_LEAVE (0xc9) // 退出指令
#define MODRM_R64(x) (((x) & 0x7) << 3) // 64位寄存器的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_R64(x) ((x) & 0x7) // 64位内存寄存器的MODRM编码
#define OP_SIZE_PREFIX (0x66) // 操作数大小前缀
#define REX_PREFIX (0x40) // REX前缀
#define REX_W (0x08) // 宽度
#define REX_R (0x04) // 寄存器
#define REX_X (0x02) // 索引
#define REX_B (0x01) // 基址
#define REX_W_FROM_R64(r64) ((r64) >> 0 & 0x08)
#define REX_R_FROM_R64(r64) ((r64) >> 1 & 0x04)
#define REX_X_FROM_R64(r64) ((r64) >> 2 & 0x02)
#define REX_B_FROM_R64(r64) ((r64) >> 3 & 0x01)
#define IMM32_L0(x) ((x) & 0xff) // 32位立即数的低8位
#define IMM32_L1(x) (((x) >> 8) & 0xff) // 32位立即数的次低8位
#define IMM32_L2(x) (((x) >> 16) & 0xff) // 32位立即数的次次低8位
#define IMM32_L3(x) (((x) >> 24) & 0xff) // 32位立即数的高8位
#define IMM64_L4(x) (((x) >> 32) & 0xff) // 64位立即数的次低8位
#define IMM64_L5(x) (((x) >> 40) & 0xff) // 64位立即数的次次低8位
#define IMM64_L6(x) (((x) >> 48) & 0xff) // 64位立即数的次次次低8位
#define IMM64_L7(x) (((x) >> 56) & 0xff) // 64位立即数的最高8位
#define UNSIGNED_FIT8(x) (((x) & 0xffffffffffffff00) == 0) // 无符号数适合8位
#define UNSIGNED_FIT32(x) (((x) & 0xffffffff00000000) == 0) // 无符号数适合32位
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) // 有符号数适合8位
static inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) {
return mp_asm_base_get_cur_to_write_bytes(&as->base, n); // 获取当前汇编器写入字节的指针
}
static void asm_x64_write_byte_1(asm_x64_t *as, byte b1) {
// 写入一个字节
byte *c = asm_x64_get_cur_to_write_bytes(as, 1); // 获取当前写入位置
if (c != NULL) {
c[0] = b1; // 写入字节
}
}
static void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) {
// 写入两个字节
byte *c = asm_x64_get_cur_to_write_bytes(as, 2); // 获取当前写入位置
if (c != NULL) {
c[0] = b1; // 写入第一个字节
c[1] = b2; // 写入第二个字节
}
}
static void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) {
// 写入三个字节
byte *c = asm_x64_get_cur_to_write_bytes(as, 3); // 获取当前写入位置
if (c != NULL) {
c[0] = b1; // 写入第一个字节
c[1] = b2; // 写入第二个字节
c[2] = b3; // 写入第三个字节
}
}
static void asm_x64_write_word32(asm_x64_t *as, int w32) {
// 写入32位立即数
byte *c = asm_x64_get_cur_to_write_bytes(as, 4); // 获取当前写入位置
if (c != NULL) {
c[0] = IMM32_L0(w32); // 写入低8位
c[1] = IMM32_L1(w32); // 写入次低8位
c[2] = IMM32_L2(w32); // 写入次次低8位
c[