从零开始实现一个汇编模拟器——初


记录一下做汇编代码模拟器的过程,根据“程序=状态机”的视角,模拟实现了汇编程序的执行过程,下面就开始进入正题吧。

第一部分:CPU

在状态机的视角下,CPU看作多个寄存器的全部状态,因而可以用一个struct来保存所有寄存器的值。同时,CPU还有MMU来实现虚拟内存向物理内存的切换(目前暂时不实现MMU的功能,而是简单的将虚拟地址取模得到物理地址)。

register.h

#ifndef _REGISTER_
#define _REGISTER_

#include <stdlib.h>
#include <stdint.h>
// 真正拥有的只有CPU和Memory.离散.状态机

typedef struct REG_STRUCT
// 这是对CPU的模拟
{
   
    union 
    {
   
        struct
        {
   
            uint8_t al;
            uint8_t ah;
        };
        uint16_t ax;
        uint32_t eax;
        uint64_t rax;
    };
    
    // 后面rbx..也是一样的写法,这边就偷懒不弄了.
    uint64_t rbx;
    uint64_t rcx;
    uint64_t rdx;
    uint64_t rsi;
    uint64_t rdi;
    uint64_t rbp;
    uint64_t rsp;

    uint64_t rip;
} reg_t;//register type

reg_t reg;

#endif

mmu.h

#ifndef _MMU_
#define _MMU_

// mmu:memory management unit 内存管理单元
// 实现虚拟地址到物理地址的翻译
#include <stdint.h>

uint64_t va2pa(uint64_t vaddr);


#endif

mmu.c

#include "cpu/mmu.h"
#include "memory/dram.h"

uint64_t va2pa(uint64_t vaddr)
{
   
    return vaddr % MM_LEN;
}

第二部分:内存

物理内存可以看作一个固定长度的数组,指令可以可以看作是操作符+操作数1+操作数2的状态机。

instruction.h

#ifndef _INSTRUCTION_
#define _INSTRUCTION_

#include <stdlib.h>
#include <stdint.h>

#define NUM_INSTRTYPE 30 //OP的数量

typedef enum OP
{
   
    mov_reg_reg,        //0
    mov_reg_mem,        //1
    mov_mem_reg,        //2
    push_reg,           //3
    pop_reg,            //4
    call,               //5
    ret,                //6
    add_reg_reg         //7
} op_t;


typedef enum OD_TYPE
{
   
    EMPTY,          
    IMM,            //立即数寻址:Imm
    REG,            //寄存器寻址:R[reg]
    MM_IMM,         //绝对寻址 :M[Imm]
    MM_REG,         //间接寻址:M[R[reg]]
    MM_IMM_REG,     //(基址+偏移量)寻址:M[Imm+R[reg]]
    MM_REG1_REG2,   //变址寻址:M[R[reg1]+R[reg2]]
    MM_IMM_REG1_REG2,   //变址寻址:M[Imm+R[reg1]+R[reg2]]
    MM_REG2_S,      //比例变址查询:M[R[reg]*S]
    MM_IMM_REG2_S,  //比例变址查询:M[Imm+R[reg]*S]
    MM_REG1_REG2_S, //比例变址查询:M[R[reg1]+R[reg2]*S]
    MM_IMM_REG1_REG2_S  //比例变址查询:M[Imm+R[reg1]+R[reg2]*S]
} od_type_t;

typedef struct OD
// 这是对操作数的模拟
{
   
    od_type_t type;

    int64_t imm;     //立即数
    int64_t scal;    //乘数
    uint64_t *reg1;  //寄存器1
    uint64_t *reg2;  //寄存器2
// 最复杂的是imm(reg1,reg2,scal)
} od_t;

typedef struct INSTRUCT_STRUCT
// 这是对指令的模拟
{
   
    op_t op;    // 操作符operator 例如mov push ..
    od_t src;   // 操作数operand
    od_t dst;   // 操作数operand
    char code[100];
} inst_t;



typedef void (*handler_t)(uint64_t,uint64_t); //handler是void*(uint64_t,uint64_t)的函数指针

handler_t handler_table[NUM_INSTRTYPE]; //函数指针数组

void init_handler_table();  //对指令集初始化

void instruction_cycle();//指令周期

void add_reg_reg_handler(uint64_t src, uint64_t dst);

void mov_reg_reg_handler(uint64_t src, uint64_t dst);

#endif

instruction.c

 // 实现译码.
#include "memory/instruction.h"
#include "cpu/mmu.h"
#include "cpu/register.h"
#include "memory/instruction.h"
#include <stdio.h>
 
static uint64_t decode_od(od_t od)
{
   
    if (od.type == IMM)
    {
   
        return *((uint64_t*)&od.imm );
    }
    else if (od.type == REG)
    {
   
        return (uint64_t)od.reg1;
    }
    else
    {
   
        // main memory
        uint64_t vaddr = 0;

        if (od.type == MM_IMM)
        {
   
            vaddr = od.imm;
        }
        else if (od.type == MM_REG)
        {
   
            vaddr = *(od.reg1);
        }
        else if (od.type == MM_IMM_REG)
        {
   
            vaddr = od.imm 
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值