Bochs源码分析 - 19:分析Bochs对于bound,into的实现

PIC单片机应用开发实践教程(四): MPLAB X IDE Debug Step Over: 执行程序的一行源代码Step Into: 执行程序的一行源代码Step Out:执行程序的一行源代码Run to Cursor (运行至光标位置): 运行当前项目,直到文件中的光标位置,并停止程序执行。Animate (连续单步运行)在运行时执行单步操作,并在运行时更新寄存器的值。连续单步运行的运行速度低于Run 功能,但它使您可以在Special Function Register (特殊功能寄存器)窗口或在Watches 窗口中查看变化的寄存器值。 阅读详情

前言

        在《x86/x64体系探索及编程》的ex10-7代码中,使用了int3,bound,into来加载CS寄存器。我们现在来尝试分析bochs对于这几条指令的实现。

into指令分析

        关于into以及处理OF异常的代码如下,比较好理解。into指令只是判断eflag的of位,这位标志着是否存在溢出发生,如果存在溢出,则触发OF异常。

;; 测试 INTO 指令 
        mov eax, 0x80000000
        mov ebx, eax
        add eax, ebx                                        ; 产生溢出,OF标志置位
        into                                                ; 引发 #OF 异常



;---------------------------------------
; OF_handler(): #OF handler
;---------------------------------------
OF_handler:
        jmp do_OF_handler
omsg1   db '---> Now, enter #OF handler',10, 10,0        

do_OF_handler:
        push ebx
        mov ebx, [esp + 12]             ; 读 eflags 值
        mov esi, omsg1
        call puts
        mov esi, ebx
        call dump_flags_value
        pop ebx
        iret

           Intel手册中对于INTO指令的描述非常简单,只是注意这是一个trap类型,而不是fault类型,我们之后会看细节,看看两种类型的实际区别,这里简单来讲,trap类型执行完后不会再来执行原指令,而fault则会再来执行原指令,int主动调用的都为trap类型。

        我们现在来用IDA逆向代码,确定其位置,然后用bochs定位,最后用visual studio看源码。

        如下bochs对于into指令的模拟代码,内容如下,这部分其实一点也不难。其基本就是调用get_OF()来判断标志位,如果满足要求的话,触发0x4号中断(overflow)。

void BX_CPP_AttrRegparmN(1) BX_CPU_C::INTO(bxInstruction_c *i)
{
  if (get_OF()) {
    BX_INSTR_FAR_BRANCH_ORIGIN();

    .....
    // interrupt is not RSP safe
    interrupt(4, BX_SOFTWARE_EXCEPTION, 0, 0);

    BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_INT,
                        FAR_BRANCH_PREV_CS, FAR_BRANCH_PREV_RIP,
                        BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP);
  }

  BX_NEXT_TRACE(i);
}

bound指令分析

        #BR异常应该含义是 bad range,越界引发的,该代码就是来触发#BR异常。

;; 测试 bound 指令
        mov eax, 0x8000                                    ; 这个值将越界
        bound eax, [bound_rang]                            ; 引发 #BR 异常

;-------------------------------------
; BR_handler(): #BR handler
;-------------------------------------
BR_handler:
        jmp do_BR_handler
brmsg1        db 10, 10, '---> Now, enter #BR handler', 10, 0        
do_BR_handler:        
        mov esi, brmsg1
        call puts
        mov eax, [bound_rang]                ; 修复错误
        iret

bound_rang        dd        10000h              ; 给定的范围是 10000h 到 20000h
                  dd        20000h

        我们现在来使用IDA,逆向这部分代码,如下图所示。        

        其代码总体来说是比较简单的,来获取大小值,之后来进行判断,如果越界则调用 exception(BX_BR_EXCEPTION, 0) 函数来触发异常。 

void BX_CPP_AttrRegparmN(1) BX_CPU_C::BOUND_GdMa(bxInstruction_c *i)
{
  Bit32s op1_32 = BX_READ_32BIT_REG(i->dst());

  Bit32u eaddr = (Bit32u) BX_CPU_RESOLVE_ADDR_32(i);

  Bit32s bound_min = (Bit32s) read_virtual_dword_32(i->seg(), eaddr);
  Bit32s bound_max = (Bit32s) read_virtual_dword_32(i->seg(), (eaddr+4) & i->asize_mask());

  if (op1_32 < bound_min || op1_32 > bound_max) {
    BX_DEBUG(("%s: fails bounds test", i->getIaOpcodeNameShort()));
    exception(BX_BR_EXCEPTION, 0);
  }

  BX_NEXT_INSTR(i);
}

        这个 exception(BX_BR_EXCEPTION, 0) 函数来触发异常,异常之后必须被对应的中断所响应,而在这里填写中断所相应的信息,其中重要部分如下所示,填写errocode之类的,之后调用interrupt(...)函数,这个函数我们已经留意很多次了,不过多叙述了。

// vector:     0..255: vector in IDT
// error_code: if exception generates and error, push this error code
void BX_CPU_C::exception(unsigned vector, Bit16u error_code)
{
    ....
 if (vector < BX_CPU_HANDLED_EXCEPTIONS) {
     push_error = exceptions_info[vector].push_error;
     exception_class = exceptions_info[vector].exception_class;
     exception_type = exceptions_info[vector].exception_type;
  }
    ....
 interrupt(vector, BX_HARDWARE_EXCEPTION, push_error, error_code);
 
 longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop 
    ....
}

struct BxExceptionInfo {
  unsigned exception_type;
  unsigned exception_class;
  bx_bool push_error;
};


struct BxExceptionInfo exceptions_info[BX_CPU_HANDLED_EXCEPTIONS] = {
  /* DE */ { BX_ET_CONTRIBUTORY, BX_EXCEPTION_CLASS_FAULT, 0 },
  /* DB */ { BX_ET_BENIGN,       BX_EXCEPTION_CLASS_FAULT, 0 },
  /* 02 */ { BX_ET_BENIGN,       BX_EXCEPTION_CLASS_FAULT, 0 }, // NMI
  /* BP */ { BX_ET_BENIGN,       BX_EXCEPTION_CLASS_TRAP,  0 },
}

        上述代码中一定要注意其返回方式,其不是用return返回的,而是使用一个longjmp(...)指令(这个longjmp指令记得在前面描述过,这里不过多叙述)。其返回到cpu_loop( )函数开头,代码如下:

void BX_CPU_C::cpu_loop(void)
{
#if BX_DEBUGGER
  BX_CPU_THIS_PTR break_point = 0;
  BX_CPU_THIS_PTR magic_break = 0;
  BX_CPU_THIS_PTR stop_reason = STOP_NO_REASON;
#endif

  // If the exception() routine has encountered a nasty fault scenario,
  // the debugger may request that control is returned to it so that
  // the situation may be examined.
#if BX_DEBUGGER
  if (bx_guard.interrupt_requested) return;
#endif

  if (setjmp(BX_CPU_THIS_PTR jmp_buf_env)) { < --- 从这里出来
    // can get here only from exception function or VMEXIT
    BX_CPU_THIS_PTR icount++;
    BX_SYNC_TIME_IF_SINGLE_PROCESSOR(0);
  }

     // We get here either by a normal function call, or by a longjmp
     // back from an exception() call.  In either case, commit the
     // new EIP/ESP, and set up other environmental fields.  This code
     // mirrors similar code below, after the interrupt() call.
      BX_CPU_THIS_PTR prev_rip = RIP; // commit new EIP
      BX_CPU_THIS_PTR speculative_rsp = 0;


    ....
    ....
    while(1){
        for(;;){
        ...
        i1->execute(...) // 我们从这里进去执行指令的
        ...
        }
    }
}

        其为什么这么走现在还看不太出来,之后我们会有单独分析exception的环节,看代码注释,合理怀疑:如果遇到嵌套的fault,此时就需要bochs的调试器接管代码,因此需要预先跳出cpu循环。

总结

        这篇文章就简单分析了这两个指令,该两个指令本身没什么难度。但是我们了解了exception(..)这个函数,异常都会走exception(..)中,然后通过longjmp(...)函数来跳转到cpu之外,之后随着我们深入分析,对其细节把握会更加深刻。

Bochs源码分析 - 8:bochs的CPU代码初步分析 前言 上一篇文章,我们分析了floppy设备的初始化,本来我们希望看看floppy的工作原理,但是调试时发现其运行cpu,通过BIOS启动指令来调用floppy。(从现在来看这是肯定的,floppy是外设,要想调用必须通过cpu,还是自己对底层不太熟悉) Bochs的CPU模块特别复杂,函数众多,我们是第一次分析,对其结构还是不太熟悉,我们先尝试来看其执行流程。在分析前,我浏览了一遍喻强老师的《Bochs项目源码分析与注释》,其CPU模块的核心图如下。 CPU模块的... 阅读详情

相关推荐

X86保护模式编程总结(6)

<br /> <br /><br />中断和异常<br />中断:<br />可屏蔽中断,在CPU的INTR引脚接收的中断请求,IF=1时才允许发生可屏蔽中断<br />不可屏蔽中断,在CPU的NMI输入脚上接收到,CPU无法关闭不可屏蔽中断.<br />异常:<br />CPU检测的异常被分为3种:<br />故障,是在已被检测到异常的指令之前的指令边界上报告的异常.故障在恢复到允许指令重新启动状态时由机器报告.用于故障处理程序的返回地址指向故障的指令,而不是指会故障指令之后的指令.<br />自陷,自陷

阿弥陀佛 僧伽吒 1470

【源码阅读】Glide源码阅读之into方法(三)

前言 上两篇中,我们阅读了glide的with和load方法的相关代码,这一篇,我们来看看into方法。 【源码阅读】Glide源码阅读之with方法(一) 【源码阅读】Glide源码阅读之load方法(二) 【源码阅读】Glide源码阅读之into方法(三) 之前,通过with和load方法,Glide创建了一个RequestBuilder,它里面保存了请求需要的相关信息,它是什么时候开始去...

weixin_33698043的博客 280

Bochs源码分析 - 11:《X86探索及编程》代码初步解释

前言 现在我们来阅读邓志老师的《x86/x64体系探索及编程》,边阅读边将其代码放到bochs中运行,然后观察bochs的CPU是如何来模拟的。现在我们来详细分析ex3-2目录里面的内容。 boot.asm 代码解读 自己在工作中经常看汇编代码,但是写汇编代码真的很少写过,我们现在一边分析着这段boot汇编代码一边回顾其如何编写。 ; Int 19h 加载 sector 0 (MBR) 进入 BOOT_SEG 段, BOOT_SEG 定义为 0x7c00 ...

WriteAnything_的博客 1021

mysql marge into_MySql实现Merge Into 功能代码

需求描述INSERT ... ON DUPLICATE KEY UPDATE SyntaxIf you specify anON DUPLICATE KEY UPDATEclause and a row to be inserted would cause a duplicate value in aUNIQUEindex orPRIMARY KEY, anUPDATEof the ...

weixin_39921504的博客 324

Bochs源码分析 - 12:这才是真正的调试姿势!!

前言 之前我们为了正确的调试bochs,采用了很多方法,一种是利用IDA进行调试,第二种是采用bochs-dbg配合调试,第三种是在cpu_loop(..)中下循环来进行调试。这三种来实际操作中都很不方便。 真正的调试姿势 IDA以二进制模式分别以0x7c00,0x8000-2为偏移打开uboot.bin与setup.bin文件,静态分析;配置调试模式编译bochs,精确下断点定位指令;再通过visual studio 在cpu_loop(..)函数中下软件断点分析指令...

WriteAnything_的博客 688

Bochs项目源码分析与注释.pdf

Bochs是一个x86硬件平台的开源模拟器。它可以模拟各种硬件的配置。Bochs模拟的是整个PC平台,包括I/O设备、内存和BIOS。更为有趣的是,甚至可以不使用PC硬件来运行Bochs。事实上,它可以在任何编译运行Bochs的平台上模拟x86硬件。通过改变配置,可以指定使用的CPU(386、486或者586),以及内存大小等。一句话,Bochs是电脑里的“PC”。根据需要,Bochs还可以模拟多台PC,此外,它甚至还有自己的电源按钮。

mysql marge into_MySQL数据库之mysql实现merge into语法的(代码实例)

mysql并不没有oracle、mssql的mergeinto语法,但是有个onduplicatekeyupdate语法(不是标准的sql语法)可以实现mergeinto语法实验一:更新所有字段mysql>select*fromdup;+------+--------+-------+|id|name|phone|+------+--------+---...

weixin_29552815的博客 441

从拆箱到跑通:Intel RealSense D435i开箱实测+ROS驱动配置全流程

本文详细记录了Intel RealSense D435i深度相机的开箱体验,并提供了在Ubuntu 22.04与ROS2 Humble环境下,从安装librealsense2 SDK到配置ROS2驱动的完整流程。重点解决了驱动安装、数据流发布、点云对齐以及IMU数据融合等关键步骤,帮助研究者和开发者快速实现D435i与机器人系统的集成。

weixin_29168393的博客 304

mysql中select into_Mysql中SELECT INTO 语句用法详解

语法介绍:把所有的列插入新表代码如下SELECT * INTO new_table_name [IN externaldatabase] FROM old_tablename只把希望的列插入新表代码如下SELECT column_name1, column_name2 INTO new_table_name [IN externaldatabase] FROM old_tablename实例1:制...

weixin_39559333的博客 3万+

Dify社区版多工作空间功能解锁:源码修改与多租户架构解析

多租户架构是现代SaaS平台实现数据隔离与资源管理的核心技术,其核心原理是通过租户模型将用户、应用和数据在逻辑上隔离。在AI应用开发平台中,这种架构能有效支持多团队、多项目并行开发,确保不同业务线的数据安全与独立迭代。Dify作为开源AI应用构建平台,其底层已设计完善的多租户模型,但社区版默认限制了单用户单工作空间。本文通过精准修改两处关键代码——账户初始化逻辑与系统功能开关,释放了平台固有的多工作空间管理能力。该方案无需改动数据库结构,直接利用现有RBAC权限体系,实现了类似企业版的**多租户隔离**体验

weixin_27059669的博客 1058

如何实现电路级别的CDM ESD防护

采用先进制程的CMOS工艺,可能具有比以前更薄的栅极氧化物和更大的芯片尺寸,大的衬底可能积累大量的电荷,导致CDM事件期间的高ESD放电峰值电流。传统CDM保护器件使用栅极接地NMOS被添加到输入级的栅极。然而,这种方法通常会在信号路径上引入显著的寄生电容,这不适合RF应用。

weixin_42693135的博客 2502

MySQL insert into 语句中字符串报错

在传入值时,在C#中代码直接传入string值,报错显示未找到符合列 command += "INSERT INTO " + TableName + "(data_id,data_desc,data_price) VALUES(" + ids[i] + ", " + description[i] + "," + price[i] + ");"+"\r\n"; 运行出错后发现是自己没有考虑到命令全...

qq_41059339的博客 1791

Unity3d游戏开发工程师笔试题学习

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、学习背景二、错题记录2.读入数据总结欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 前言 提示:这里可以.

m0_54231818的博客 5464

一次调用执行两次insert into_这段代码让程序执行效率提升200倍,值得一看

前言前几天业务系统部门将我们数据平台给投诉了,因为在工作时间内,业务系统查询不到想要的数据,这种问题可大可小,但毕竟影响到了业务的正常运行,所有的技术都是为业务服务的,所以不论技术难度大小,必须要进行整改,同时作为互联网的‘工匠精神’,我们不光要让功能正常运行,还要让功能以最优的状态运行。系统介绍整个系统可以从功能上分为3块:业务系统:在上游有很多的业务系统,业务系统的运行产生很多的数据,这些数据...

weixin_39714113的博客 483

恶意代码实验3:Word宏病毒实验

只要下次打开这个word文档,就会执行以上代码,并将自身复制到Normal.dot(word文档的公共模板)和当前文档的ThisDocument中,同时改变函数名(模板中为Document_Close,当前文档为Document_Open),此时所有的word文档打开和关闭时,都将运行以上的病毒代码,可以加入适当的恶意代码,影响word的正常使用,本例中只是简单的跳出一个提示框。回答不正确三次,即可自动跳出病毒程序,但那时已经出现几十个文档。1、打开的宏编辑器如图所示,即可编写病毒代码。

qq_63949327的博客 6505

MSVS C# Matlab的混合编程系列2 - 构建一个复杂(含多个M文件)的动态库:

本节我们尝试将一个有很多函数和文件的Matlab算法文件集成到C#的项目里面。

山云的专栏 2068

mysql的merge_MySQL数据库之mysql实现merge into语法的(代码实例)

本文主要向大家介绍了MySQL数据库之mysql实现merge into语法的(代码实例) ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助。mysql实现mergeinto语法的(代码实例)mysql并不没有oracle、mssql的mergeinto语法,但是有个onduplicatekeyupdate语法(不是标准的sql语法)可以实现mergeinto语法实验...

weixin_29698317的博客 5385

(全网最详细教程)康耐视读码器(以DM260S为例子)详细实用步骤

(全网最详细教程)康耐视读码器(以DM260S为例子)详细实用步骤

视觉人机器视觉的博客 7465

Debugging into .NET Core源代码的两种方式

一、前言   .NET开源时间还不长,因为一直在做YOYOFx的关系,所似我常常有更深入的了解.NET Core和ASP.NET Core内容的需求,并且.NET Core平台与之前版本的变化太大,这也导致我经常要去查看源代码中,来了解ASP.NET Core和.NET Core代码实现。   的确,.NET Core和ASP.NET Core的源代码,现在已经在Github上进行了代码托管...

weixin_30363817的博客 172

【四足机器人实战】四足机器人运动学、动力学模型

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!四足机器人的运动学和动力学模型是其设计和控制的基础,涉及到如何精确描述和预测机器人在不同条件下的运动状态和行为本文先对四足机器人运动学、动力学模型做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章运动学模型主要关注四足机器人的几何形态和时间序列下的运动特性,而动力学模型则进一步考虑了引起这些运动的力和扭矩的作用效果。运动学模型:运动学模型描述了四足机器人在没有考虑力的影响下的运动特性。

qq_35635374的博客 1055

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

mysql merge update_mysql实现merge into语法的(代码实例)

mysql实现merge into语法的(代码实例)mysql并不没有oracle、mssql的merge into语法,但是有个on duplicate key update语法(不是标准的sql语法)可以实现merge into语法实验一:更新所有字段mysql> select * from dup;+------+--------+-------+| id | name | p...

weixin_34036423的博客 985

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Bochs源码分析 - 5: 从启动到cpu运行之前的一系列初始化

前言 现在正式开始调试bochs源代码,在这之前我也没读过bochs源码,算是从零开始读,自己可能会走入一些误区,有些可能猜错,如果发现之后会来改正。我们先大体走一遍整个系统,不要纠结于各种复杂细节流程。 这篇文章开始分析程序在点击启动后如何开始并且一步步初始化完成初始化,完成相关配置文件。说实话,如下图bochs启动时一系列的配置参数,对像我这种新手来说是相当恐怖的,各种启动参数信息。其实调试过一遍之后,虽然里面很多细节还是不太懂,但是再看这些信息心里踏实多了。 启...

WriteAnything_的博客 1313

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Bochs源码分析-CPU类

因为学习需要,要看虚拟机Bochs的源代码。写随笔主要为了学习总结,其次是分享大家共同研究,大神勿喷,欢迎评论。 手头资料:bochs源代码,下于:bochs.sourceforge.net,还有喻强写的源码分析电纸书。 在Bochs模拟机里面CPU类是最复杂的一个类,也是最重要的一个类。原因很简单,在整个计算机体系中CPU处于中心位置,计算机其它部件都是在CPU的调控下进行有序的工作,当然C...

weixin_30635053的博客 267

Bochs源码分析 - 6: bochs的物理内存初始化

前言 上一篇文章,我们走马观花地介绍了bochs从启动到CPU执行流程的大体流程,里面相关数据结构没详细分析。这篇文章我们尝试来详细分析一下bochs的物理内存初始化,首先有个概念需要理清(相信来看bochs源码的人肯定会知道):bochs只负责处理物理内存,而虚拟内存是运行在bochs中运行的OS来负责的,我们只需要关注物理内存。 找到内存初始化函数 在上篇文章中,我们提到过一个比较重要的函数bx_init_hardware(),该函数负责初始化各种硬件(内存,Io...

WriteAnything_的博客 941

逆向入门(9)汇编篇-bound指令的学习

看程序的时候碰到这么一行没见过的代码,简单记录一下这里是用到了bound指令,这是x86汇编中的指令,用于检查数组索引是否在有效范围内。

baynk的博客 1343

Bochs源码分析 - 17:分析Bochs对于int指令的实现

前言 在《x86/x64编程体系探索及编程》的第207页,其举了一个使用中断服务例程的例子,我们现在来分析其源码以及探究bochs是如何实现的(重点探究int指令)。 代码分析 其首先设置好调用set_user_interrupt_handler来调用中断向量,内容如下: mov esi, SYSTEM_SERVICE_VECTOR // 0x40 mov edi, system_service // lib ...

WriteAnything_的博客 633
上一篇: Bochs源码分析 - 18:分析Bochs对于iret指令的实现
下一篇: Bochs源码分析 - 20: 开启保护模式
WriteAnything_
博客等级 码龄5年 66粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值