microPython的源码解析之 asmx64.c

本文详细解读MicroPython的asmx64.c文件,探讨其在x64架构下生成汇编代码的逻辑,包括初始化、函数入口/出口、局部变量处理、数据移动、控制流操作和优化。同时,文中还提供了若干C语言示例,展示如何在NI-Motion运动控制应用中执行不同任务。
摘要由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_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[
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

openwin_top

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

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

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

打赏作者

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

抵扣说明:

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

余额充值