microPython的源码解析之 asmx86.c

本文详细解析MicroPython的asmx86.c,介绍如何通过C语言生成x86汇编代码,涉及初始化配置、指令生成、内存管理、控制流和函数调用等关键步骤,帮助读者掌握Python解析器的核心实现逻辑。
摘要由CSDN通过智能技术生成

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
  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值