实现8086虚拟机(四)——mov 和 jmp 指令解码
文章目录
- mov 指令解码
- jmp 指令解码
这篇文章举例来讲讲 mov 指令和 jmp 指令解码函数的实现,其他的指令解码函数都与这些类似。
mov 指令解码
以 mov 指令中的一类:寄存器/内存 到/从 寄存器,来详细说明解码函数的实现。
机器指令格式如下:

各字段的含义如下:
w 1 bit w=0表示数据宽度是字节,w=1表示数据宽度是字
d 1 bit d=0表示reg是源操作数,d=1表示reg是目的操作数
reg 3 bitsREG W=0 W=1000 AL AX001 CL CX010 DL DX011 BL BX100 AH SP101 CH BP110 DH SI111 BH Dl
mod 2 bits00 MemoryMode,nodisplacement follows01 MemoryMode,8-bit displacementfollows10 MemoryMode,16-bit displacementfollows11 RegisterMode(no displacement)
rm 3 bitsMOD=11 EFFECTIVE ADDRESS CALCULATIONR/M w=0 w=1 R/M MOD=00 MOD=01 MOD=10000 AL AX 000 (BX)+(SI) (BX)+(SI)+D8 (BX)+(SI)+D16001 CL CX 001 (BX)+(DI) (BX)+(DI)+D8 (BX)+(DI)+D16010 DL DX 010 (BP)+(SI) (BP)+(SI)+D8 (BP)+(SI)+D16011 BL BX 011 (BP)+(DI) (BP)+(DI)+D8 (BP)+(DI)+D16100 AH SP 100 (SI) (SI)+D8 (SI)+D16101 CH BP 101 (DI) (DI)+D8 (DI)+D16110 DH SI 110 DIRECTADDRESS (BP)+D8 (BP)+D16111 BH DI 111 (BX) (BX)+D8 (BX)+D16
解码函数 decodeMovRegOrMemoryToFromReg 的目的就是将它转换为如下形式的中间指令格式:
指令类型,指令详细类型,[源操作数],[目的操作数]
decodeMovRegOrMemoryToFromReg 函数首先检测输入的机器指令的长度:
func decodeMovRegOrMemoryToFromReg(instructions []byte) []byte {/* 0b100010dw,mod reg r/m, (DISP-LO ), (DiSP-HI)*/decodegth := len(instructions)if decodegth < 2 {return nil}dispLen := lenDisplacement(instructions[1])if decodegth < 2+dispLen {return nil}....
}
由上文机器指令格式可知,这个指令至少有 2 字节长。如果长度达到 2 字节,再调用 lenDisplacement 获取偏移量的长度。如果指令长度达不到指令格式的要求,说明不是一条完整的指令,那就返回 nil。
lenDisplacement 的实现如下:
/* mod xxx r/m, (DISP-LO ), (DiSP-HI) */
func lenDisplacement(secondByte byte) int {mod := (secondByte & 0b11000000) >> 6rm := secondByte & 0b111if mod == 0b11 {return 0}if mod == 0b00 { /* mov bx, [1]*/if rm == 0b110 {return 2}return 0}if mod == 0b01 {return 1}return 2
}
就是根据 mod 和 rm 字段的含义返回偏移量的长度。
然后就是根据 d、w、mod、rm、reg 字段的含义,确定指令详细类型和操作数,将中间形式的指令格式返回:
decodedInstructions := []byte{InstructionMov}// return 2 + dispLend := (instructions[0] & 0b10) >> 1w := instructions[0] & 0b1mod := (instructions[1] & 0b11000000) >> 6reg := (instructions[1] & 0b111000) >> 3rm := instructions[1] & 0b111switch mod {case 0b11: //RegisterMode(no displacement)if w == 0 {decodedInstructions = append(decodedInstructions, MovReg8ToReg8)} else {decodedInstructions = append(decodedInstructions, MovReg16ToReg16)}if d == 0 { //reg是源操作数decodedInstructions = append(decodedInstructions, reg)decodedInstructions = append(decodedInstructions, rm)} else {decodedInstructions = append(decodedInstructions, rm)decodedInstructions = append(decodedInstructions, reg)}default:if d == 0 {if w == 0 {decodedInstructions = append(decodedInstructions, MovReg8ToMemory)} else {decodedInstructions = append(decodedInstructions, MovReg16ToMemory)}decodedInstructions = append(decodedInstructions, reg)decodedInstructions = append(decodedInstructions,decodeMemoryOperand(mod, rm, instructions[2:])...)} else {if w == 0 {decodedInstructions = append(decodedInstructions, MovMemoryToReg8)} else {decodedInstructions = append(decodedInstructions, MovMemoryToReg16)}decodedInstructions = append(decodedInstructions,decodeMemoryOperand(mod, rm, instructions[2:])...)decodedInstructions = append(decodedInstructions, reg)}}return decodedInstructions
比如,当 mod 字段为 0b11 时,表示两个操作数都是寄存器,如果 d 为 0,那么 reg 字段就是源操作数,rm 字段就是目的操作数。如果 w 为1,那么操作数的宽度就是16位。这时候生成的中间指令格式为:
InstructionMov,MovReg16ToReg16 ,reg , rm
如果 reg 的值是 0,rm 的值是 1,这条指令的源汇编指令就是:
mov ax,cx
就是这么简单。
再看下解码 mov 立即数到内存/寄存器 解码函数 decodeMovImmediateToRegOrMemory 的实现:
func decodeMovImmediateToRegOrMemory(instructions []byte) []byte {/*1100011w, mod 000 rm, [disp-lo] [disp-hi] data [data]*/decodegth := len(instructions)if decodegth < 2 {return nil}w := instructions[0] & 0x1dispLen := lenDisplacement(instructions[1])dataLen := 1if w == 1 {dataLen = 2}if decodegth < 2+dispLen+dataLen {return nil}decodedInstructions := []byte{InstructionMov}mod := (instructions[1] & 0b11000000) >> 6rm := instructions[1] & 0b111if w == 0 {if mod == 0b11 {decodedInstructions = append(decodedInstructions, MovImmediateToReg8)decodedInstructions = append(decodedInstructions, instructions[2])decodedInstructions = append(decodedInstructions, rm)} else {decodedInstructions = append(decodedInstructions, MovImmediate8ToMemory)decodedInstructions = append(decodedInstructions, instructions[decodegth-1])decodedInstructions = append(decodedInstructions,decodeMemoryOperand(mod, rm, instructions[2:decodegth-1])...)}} else {if mod == 0b11 {decodedInstructions = append(decodedInstructions, MovImmediateToReg16)decodedInstructions = append(decodedInstructions, instructions[2])decodedInstructions = append(decodedInstructions, instructions[3])decodedInstructions = append(decodedInstructions, rm)} else {decodedInstructions = append(decodedInstructions, MovImmediate16ToMemory)decodedInstructions = append(decodedInstructions, instructions[decodegth-2])decodedInstructions = append(decodedInstructions, instructions[decodegth-1])decodedInstructions = append(decodedInstructions,decodeMemoryOperand(mod, rm, instructions[2:decodegth-2])...)}}return decodedInstructions
}
其他的都类似。
jmp 指令解码
jmp 指令包含直接转移和条件转移。
decode_jmp.go 中先把所有的指令详细类型定义出来:
const (//非条件转移JmpNotShort uint8 = iota //16位IP偏移量JmpShort //8位IP偏移量JmpDirectIntersegment //cs 16位,IP 16位JmpReg16 //IP的值在寄存器中JmpIndirectWithinsegmentJmpIndirectIntersegment//条件转移JmpJoJmpjnoJmpJbJmpJnbJmpJeJmpJneJmpJbeJmpJnbeJmpJsJmpJnsJmpJpJmpJnpJmpJlJmpJnlJmpJleJmpJnleJmpJcxz
)
初始化函数,注册所有的 jmp 指令与它的解码函数:
func init() {//jmpAddDecodeInstruction(0xE9, decodeJmpDirectWithinsegment)AddDecodeInstruction(0xEA, decodeJmpDirectIntersegment)AddDecodeInstruction(0xEB, decodeJmpDirectWithinsegmentShort)AddDecodeInstruction2(0xFF, 0b100, decodeJmpIndirectWithinsegment)AddDecodeInstruction2(0xFF, 0b101, decodeJmpIndirectIntersegment)var firstByte bytefor firstByte = 0x70; firstByte <= 0x7F; firstByte++ {AddDecodeInstruction(firstByte, decodeJmpConditional)}//jcxzAddDecodeInstruction(0xE3, decodeJmpConditional)}
以段内间接转移为例,它的机器指令格式如下:

对应的解码函数 decodeJmpIndirectWithinsegment 代码如下:
func decodeJmpIndirectWithinsegment(instructions []byte) []byte {/*11111111,mod 1 0 0 r/m,(DISP-LO ) (DISP-HI)*/decodegth := len(instructions)if decodegth < 2 {return nil}dispLen := lenDisplacement(instructions[1])if decodegth < 2+dispLen {return nil}decodedInstructions := []byte{InstructionJmp}mod := (instructions[1] & 0b11000000) >> 6rm := instructions[1] & 0b111if mod == 0b11 {decodedInstructions = append(decodedInstructions, JmpReg16)decodedInstructions = append(decodedInstructions, rm)} else {decodedInstructions = append(decodedInstructions, JmpIndirectWithinsegment)decodedInstructions = append(decodedInstructions,decodeMemoryOperand(mod, rm, instructions[2:])...)}return decodedInstructions
}
如果 mod 是 0b11,则返回的中间形式机器指令为:
InstructionJmp,JmpReg16,rm
条件转移的解码函数就更简单,因为条件转移的机器指令固定 2 个字节:

只需根据第一个字节确定详细指令类型即可,它的实现如下:
func decodeJmpConditional(instructions []byte) []byte {/*xxxxxxxx,IP-INC8*/if len(instructions) < 2 {return nil}table := map[uint8]uint8{0x70: JmpJo,0x71: Jmpjno,0x72: JmpJb,0x73: JmpJnb,0x74: JmpJe,0x75: JmpJne,0x76: JmpJbe,0x77: JmpJnbe,0x78: JmpJs,0x79: JmpJns,0x7A: JmpJp,0x7B: JmpJnp,0x7C: JmpJl,0x7D: JmpJnl,0x7E: JmpJle,0x7F: JmpJnle,0xE3: JmpJcxz,}return []byte{InstructionJmp, table[instructions[0]], instructions[1]}
}
其他指令的解码函数实现都类似。
后续文章讲解 EU 如何实现执行 mov,jmp 以及一些算数运算指令。
相关文章:
实现8086虚拟机(四)——mov 和 jmp 指令解码
文章目录mov 指令解码jmp 指令解码这篇文章举例来讲讲 mov 指令和 jmp 指令解码函数的实现,其他的指令解码函数都与这些类似。mov 指令解码 以 mov 指令中的一类:寄存器/内存 到/从 寄存器,来详细说明解码函数的实现。 机器指令格式如下&am…...
数据库技术-函数依赖、键与约束、范式
一、函数依赖 给定一个x,能唯一确定一个Y,就称x确定Y,或者说Y依赖于x,例如YX*X函数。 函数依赖又可扩展以下两种规则: 部分函数依赖:A可确定C,(A,B)也可确定C,(A,B)中的一部分(即A)可以确定C&a…...
shiro CVE-2020-1957
0x00 前言 在之前只是单纯的复现了漏洞,没有记笔记,所以补充了这篇分析笔记。 影响版本:shiro < 1.5.2 0x01 环境搭建 环境用的是:https://github.com/lenve/javaboy-code-samples/tree/master/shiro/shiro-basic 0x02 漏…...
RabbitMQ 入门到应用 ( 五 ) 基本应用
6.更多应用 6.1.AmqpAdmin 工具类 可以通过Spring的Autowired 注入 AmqpAdmin 工具类 , 通过这个工具类创建 队列, 交换机及绑定 import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Di…...
部署dapr的辛酸历程
前言dapr大概的了解,个人理解他就是一个分布式服务的管理,把微服务常用的组件(缓存,消息中间件、分布式锁、安全id4等)和监控以及服务注册、发现等等一系列功能以一个很抽象的方式管理起来。可能我们部署微服务用consul、ocelot、polly套件、…...
golang入门笔记——内存管理
文章目录自动内存管理概念自动内存管理-相关概念:追踪垃圾回收:分代GC(Generational GC)引用计数内存分配Go内存分配-分块Go内存分配——多级缓存Go内存管理优化Balanced GC自动内存管理 概念 1.动态内存 程序在运行时根据需求…...
97. 约数之和
Powered by:NEFU AB-IN Link 文章目录97. 约数之和题意思路代码97. 约数之和 题意 假设现在有两个自然数 A和 B,S是 A^B的所有约数之和。 请你求出 S mod 9901的值是多少。 思路 ABA^BAB的约数之和为:sumAB(1p1p12...p1Ba1)(1p2p22...p2Ba2)...sum_{A^B…...
想和20岁的自己说
男生床头千万不要放卫生纸不要叫自己的女朋友早睡,更不能叫她早起,否则有你好受的。成年人的默契:和异性单独出去旅游,如果没有明确拒绝开一间房,那基本上默认后面会发生的事情不要去考验人性,世上99%的人经…...
Unit Test and Integration Test
Unit Test and Integration Test Background It is the first time that I try to write an article in English. In the past, I didn’t write test code. Just thinking QA is responsible for testing. As a developer, I don’t need to care about tests. Although I …...
2022年全国职业院校技能大赛(中职组)网络安全竞赛试题(3)
目录 模块A 基础设施设置与安全加固 (本模块20分) 一、项目和任务描述: 假定你是某企业的网络安全工程师,对于企业的服务器系统,根据任务要求确保各服务正常运行,并通过综合运用用户安全管理与密码策略、…...
智慧城市应急指挥中心数字化及城市驾驶舱建设方案
目 录 第一章 项目概述 1.1 项目背景 1.2 项目范围 第二章 建设内容 2.1 三维可视化平台 2.1.1 多源数据接入 2.1.2 可视化编排 2.1.3 三维可视化编辑 2.1.4 空间数据可视化 2.1.5 集成框架支持 2.2 可视化场景定制开发 2.2.1 城市驾驶总舱 2.2.2 城市安全分舱 2.…...
HSCSEC 2023 个人练习
😋 大家好,我是YAy_17,是一枚爱好网安的小白。本人水平有限,欢迎各位大佬指点,欢迎关注😁,一起学习 💗 ,一起进步 ⭐ 。⭐ 此后如竟没有炬火,我便是唯一的光。…...
Android 基础知识4-2.7 RelativeLayout(相对布局)
一、RelativeLayout的概述 RelativeLayout(相对布局)是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。在很多时候,线性布局还不能满足我们的需求,比如,我们在一行(列)上显示多个控…...
关于云计算,我们问了ChatGPT 10个问题
ChatGPT懂云计算吗?前些天,我们问了ChatGPT(非Plus收费版)一些问题。1. 什么是云计算?2. 云计算行业的护城河是什么?3. 什么是云原生?4. 微软Azure与亚马逊AWS的主要区别是什么?5. 为…...
Netty学习笔记1
Netty学习笔记(一) 在的互联网环境下,分布式系统大行其道,而分布式系统的根基在于网络编程,而 Netty 恰恰是 Java 领域网络编程的王者。如果要致力于开发高性能的服务器程序、高性能的客户端程序,必须掌握…...
RISK-V品牌的中国化历程(中)
目录 1.技术优势 出道即巅峰 2.生态布道 品牌根植中国 3.应用场景 加速品牌的商业化运作 生态布道 品牌根植中国 2015年成立非盈利组织RISC-V基金会,目前已吸引全球28个国家327家会员,包括英伟达、联发科、苹果、特斯拉、谷歌、高通、IBM、三星、麻省理…...
2023.02.19 学习周报
文章目录摘要文献阅读1.题目2.摘要3.介绍4.本文贡献5.方法5.1 Local Representation Learning5.2 Global Representation Learning5.3 Item Similarity Gating6.实验6.1 数据集6.2 结果7.结论深度学习1.对偶问题1.1 拉格朗日乘数法1.2 强对偶性2.SVM优化3.软间隔3.1 解决问题3.…...
枚举类的使用方法
一、理解枚举类型 枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。下面先来看看如何写…...
.NET3.5安装步骤及相关问题。
.NET3.5全称 Microsoft.NETFramework3.5 最新版本-.NET4.8 第一步打开控制面板 windows系统打开控制面板 选择程序 选择.NET3.5安装。 可能会出现问题。 解决方案: 报错代码80240438的常用解决办法: 方法一:检测windows update servic…...
联想M7268激光打印机开机红绿灯双闪报错不打印
故障现象: 一台联想M7268激光打印机开机后电源键、复印键一起双闪,电源键闪红灯、复印键闪绿灯; 检测维修: 根据闪灯故障判断如果无卡纸异常情况下可能是激光器故障,因为以前曾经维修过一台一模一样的机器故障基本相同,先打开机器吧,把硒鼓拿出来先看看有没有卡纸,进纸…...
Taotoken的TokenPlan套餐如何实现更经济的模型调用
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken的TokenPlan套餐如何实现更经济的模型调用 1. 理解TokenPlan的计费模式 在模型应用开发过程中,成本的可预测性…...
第三幕 御酒掺土,江山为祭
金牌监制,您这一刀改得极其精准,直接把整部戏的格局从“江湖恩怨”拉升到了“家国博弈”的层面!确实,如果只谈慈悲,唐三藏只是个高僧;但如果加上李世民的重托和大唐的国运,他就是一个背负着沉重…...
百考通智能任务书:贴合你的选题,拒绝空话假大空
毕业设计任务书是高校教学管理中的关键环节,它不仅标志着研究工作的正式启动,更是后续开题、实施、论文撰写和答辩全过程的行动依据。然而,许多学生在撰写时常常因不熟悉本专业写作规范、技术表达能力有限,或缺乏权威模板参考而陷…...
独立站内容分层:一层给 SEO,一层给 GEO
你的内容在喂两个完全不同的"阅读者" 你的博客文章,从来都不只有一个读者。 传统认知里,独立站内容的读者只有两类:真人访客和搜索引擎爬虫。SEO 优化的一切工作,本质上都是在讨好后者,顺带服务前者。 但…...
PS5 NOR Modifier深度解析:如何通过Windows工具修复PS5硬件故障与实现光驱版转数字版
PS5 NOR Modifier深度解析:如何通过Windows工具修复PS5硬件故障与实现光驱版转数字版 【免费下载链接】PS5NorModifier The PS5 Nor Modifier is an easy to use Windows based application to rewrite your PS5 NOR file. This can be useful if your NOR is corru…...
第2章 谁在危险中——被AI替代的五类程序员
第2章 谁在危险中——被AI替代的五类程序员 核心问题:哪些程序员最容易被AI替代?背后的原因是什么? 2.1 问题定义:一场正在发生的结构性塌陷 2.1.1 数据不会说谎 2026年1月12日,Ravio发布了一份让整个科技圈沉默的报告:过去一年,初级开发者岗位招聘量暴跌73%。 不是…...
3大突破性功能:用HiveWE革新你的魔兽争霸III地图创作体验
3大突破性功能:用HiveWE革新你的魔兽争霸III地图创作体验 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE 还在为传统魔兽争霸III编辑器缓慢的加载速度和复杂的操作界面而烦恼吗?Hive…...
如何高效实现Windows自动化鼠标点击:AutoClicker完整实战指南
如何高效实现Windows自动化鼠标点击:AutoClicker完整实战指南 【免费下载链接】AutoClicker AutoClicker is a useful simple tool for automating mouse clicks. 项目地址: https://gitcode.com/gh_mirrors/au/AutoClicker AutoClicker是一款专业的Windows桌…...
从XAI到HXAI:构建以人为中心的可解释AI框架与实践
1. 项目概述:从“黑箱”到“白盒”,构建可信AI的演进之路在机器学习项目里摸爬滚打了十几年,我见过太多因为模型“说不清道不明”而引发的信任危机。一个在测试集上表现完美的信用评分模型,可能因为无法向风控专家解释“为什么拒绝…...
SafeExamBrowser安全绕过实战:虚拟机检测绕过与日志伪装技术架构深度解析
SafeExamBrowser安全绕过实战:虚拟机检测绕过与日志伪装技术架构深度解析 【免费下载链接】safe-exam-browser-bypass A VM and display detection bypass for SEB. 项目地址: https://gitcode.com/gh_mirrors/sa/safe-exam-browser-bypass SafeExamBrowser&…...
