nemu_API

原文链接

PA 中有许多接口函数,可以供我们直接调用,特别方便,但是得先了解各个参数和功能,现在把它们总结在这里,方便以后查阅

以下将guest客户地址写做虚拟地址,将host地址写做实际地址。

地址转换

  • guest_to_host(p)

将一个 uint32_t 类型的虚拟地址转换为 void * 的实际地址

  • host_to_guest(p)

与上一个相反

I/O 相关

  • uint32_t vaddr_read(vaddr_t, int);

从虚拟地址 vaddr_t 出读取 int 字节的数据,最多为四个字节。

  • uint32_t paddr_read(paddr_t, int);

和上一个没什么区别。。可能以后会改吧。

  • void vaddr_write(vaddr_t, int, uint32_t);

将 int 字节的数据 uint32_t 写入虚拟地址 vaddr_t,

  • void paddr_write(paddr_t, int, uint32_t);

同上。。

ModRM 相关

  • void operand_write(Operand , rtlreg_t );

将右边指针指向的数据 写入 左边的操作数(reg or mem)

译码相关

  • make_DHelper(XXX);

宏展开:decode_xxx 函数

  • make_EHelper(XXX);

宏展开:exec_xxx 函数

  • make_DopHelper(XXX);

宏展开:decode_op_xxx 函数

前缀

  • make_EHelper(operand_size);

操作数前缀,转为 16 位操作数

  • static make_EHelper(2byte_esc);

双字节指令前缀

RTL基本指令

  • rtl_li(rtlreg_t* dest, uint32_t imm)

载入立即数

  • rtl_(add|sub|and|or|xor|shl|shr|sar|slt|sltu)

算术运算和逻辑运算, 寄存器-寄存器类型

  • rtl_(add|sub|and|or|xor|shl|shr|sar|slt|sltu)i

算术运算和逻辑运算, 立即数-寄存器类型

  • rtl_lm(rtlreg_t dest, const rtlreg_t addr, int len)

内存访问

  • rtl_sm(rtlreg_t addr, int len, const rtlreg_t src1)

内存存储

  • rtl_lr_(b|w|l)(rtlreg_t* dest, int r)

通用寄存器访问

  • rtl_sr_(b|w|l)(rtlreg_t* dest, int r)

通用寄存器存储

  • rtl_lr(rtlreg_t* dest, int r, int width)

带宽度的寄存器读取

  • rtl_sr(rtlreg_t* dest, int r, int width)

带宽度的寄存器存储

  • rtl_set_(CF|OF|ZF|SF|IF) 和 rtl_get_(CF|OF|ZF|SF|IF)

EFLAGS标志位读写

  • rtl_mv(rtlreg_t dest, const rtlreg_t src1)

数据移动

  • rtl_not(rtlreg_t* dest)

按位非

  • rtl_sext(rtlreg_t dest, const rtlreg_t src1, int width)

符号扩展

  • rtl_(push|pop)

数据压栈、出栈

  • rtl_(eq0|neq0)(rtlreg_t dest, const rtlreg_t src1)

判断源操作数是否为0

  • rtl_eqi(rtlreg_t dest, const rtlreg_t src1, int imm)

判断源操作数是否等于立即数

DopHelper

  • A 直接寻址
  • G ModR_M 中的 reg 域 指定 general register
  • C ModR_M 中的 reg 域 指定 control register
  • D ModR_M 中的 reg 域 指定 debug register
  • S ModR_M 中的 reg 域 指定 segment register
  • T ModR_M 中的 reg 域 指定 test register
  • E 操作数是 通用寄存器 或 内存地址
  • F 标志寄存器
  • I 立即数
  • J 指令中包含相对偏移地址
  • M ModR_M 仅指定 内存
  • O 指令无 ModR_M 字节
  • R ModR_M 中 mod 域 指定 general resister
  • X SI
  • Y DI

  • c 字节 或 字
  • v 字 或 双字
  • b 字节
  • w 字
  • d 双字
  • p 32-bit 或 48-bit 的指针
  • s 6 字节的伪描述符
  • a 两个字 或 两个双字(取决于 operand_size)

杂项

  • make_group(name, …);

group 类型,需要进一步解析 ModRM 的 reg/opcode 字节 来确定真正的指令

  • make_EHelper(real);

读取操作码,操作码写入 decoding.opcode,操作数宽度写入 src(dest, src1).width,然后执行 opcode_table 中的 译码函数 和 解码函数

  • IDEXW(id, ex, w);

将要用到的,译码函数 decode_id, 执行函数 exec_ex,操作数宽度 w

  • idex(vaddr_t eip, opcode_entry e);

解码(instr decode)和执行(execute)

调试设置

  • 更改默认AM

nexus-am/Makefile.check文件夹中
-ARCH ?= native
+ARCH ?= x86-nemu

  • 更改调试器

nexus-am/am/arch/x86-nemu/img/run文件夹中
-make -C $NEMU_HOME run ARGS=”-l dirname $1/nemu-log.txt $1.bin”
+make -C $NEMU_HOME gdb ARGS=”-l dirname $1/nemu-log.txt $1.bin”

  • Differential test

在nemu/include/common.h中定义宏DIFF_TEST

标志位

ZF(零标志位),SF(符号标志位),OF(溢出标志位),CF(进位标志位),IF(中断标志位)。

nexus-am API

  • unsigned long _uptime()用于返回系统启动后经过的毫秒数
  • int _read_key()用于返回按键的键盘码, 若无按键, 则返回_KEY_NONE
  • _Screen _screen结构用于指示屏幕的大小
  • void _draw_rect(const uint32_t *pixels, int x, int y, int w, int h) 用于将pixels指定的矩形像素绘制到屏幕中以(x, y)和(x+w, y+h)两点连线为对角线的矩形区域
  • void _draw_sync()用于将之前的绘制内容同步到屏幕上 (在NEMU中绘制内容总是会同步到屏幕上, 因而无需实现此API)
  • void _ioe_init()用于进行IOE相关的初始化工作, 调用后程序才能正确使用上述IOE相关的API

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 地址转换
  2. 2. I/O 相关
  3. 3. ModRM 相关
  4. 4. 译码相关
  5. 5. 前缀
  6. 6. RTL基本指令
  7. 7. DopHelper
  8. 8. 杂项
  9. 9. 调试设置
  10. 10. 标志位
  11. 11. nexus-am API