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

【元宵快乐】猜灯谜吃元宵 元气满满闹元宵~(附猜灯谜小游戏)

导语 元宵节,又称上元节、灯节,是春节之后的第一个重要节日。 相传,汉文帝(前179—前157年)为庆祝周勃于正月十五勘平诸吕之乱,每逢此夜,必出宫游玩,与民 同乐,在古代,夜同宵,正月又称元月,汉文帝就将正月十五定为元宵节。 随着社会和时代的变迁,元宵节的风俗习惯在不断变化,但至今仍是中国的传统节日。2008年, 元宵节选入第二批国家级非物质文化遗产。 对我而言,除了吃元宵、看花灯……还有一件最重要的事情…就是… 猜灯谜!猜灯谜!!猜灯谜!!!猜谜事小,展现聪明才智事大哈哈哈.jpg .

顾木子吖的博客 2098

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万+

SPI 协议帧格式深度解析:从 8 位数据到 16 位扩展的 3 种模式

本文深入解析SPI协议的帧格式,涵盖从8位标准到16位扩展的三种模式。通过详细讲解SPI时钟模式、数据宽度配置及实际应用案例,帮助开发者掌握SPI外设的深度定制能力,提升嵌入式系统开发效率。特别适用于连接传感器、存储器和显示器等高速通讯场景。

weixin_34110749的博客 345

测试用例经典练习之微信发红包测试用例

微信发红包测试用例

ZCYaiCLX3344的博客 1万+

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

C#调用Halcon程序三种方法

C#调用Halcon程序三种方法 1.halcon导出C#文件,在C#里面调用 2.在C#里面使用Halcon引擎调用Halcon程序 3.在C#里面使用Halcon引擎调用.hdev下本地函数或者.hdvp外部函数 Halcon引擎手册:C:/Program Files/MVTec/HALCON-21.11-Progress/doc_en_US/html/manuals/programmers_guide/programmers_guide_0120.html 1.导出C#(代码我只给出类,需要调用)

A541925504的博客 1万+

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

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

weixin_39714113的博客 483

开关电源|控制方式PWM、PFM、混合调制

频率调制器根据误差放大器的输出大小来改变方波信号的频率,若负载电流突然增加,输出电压 Vout随之下降,反馈电压 VFB 减小,此时误 差放大器的输出增高,频率调制器输出方波信号的频率增大,增加电感充电次数;若负载电流突然增加,输出电压Vom随之下降,反馈电压Vr减小,此时误差放大器的输出增高,PWM比较器输出方波信号的占空比增大,增加电感充电时间:若负载电流突然下降,PWM比较器输出方波信号的占空比减小,减少电感充电时间,从而稳定输出电压。它是在固定开关频率下,通过改变脉冲宽度来调节占空比的。

weixin_46969363的博客 1万+

第4章--CANoe library开发 - 诊断功能

因为专栏要做的是汽车ECU自动化测试程序,测试的是ECU的诊断和刷新,因此就需要利用CANoe的接口,开发一些方便使用的诊断报文收发函数。

j187067046的博客 1398

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

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

weixin_29698317的博客 5385

Python在振动信号处理中的应用(一):振动信号消除多项式趋势项

文章目录一、概述二、最小二乘法去除趋势项原理三、python模块介绍3.1 scikitlearn简介(1)转化器(Transformer)(2)估计器(Estimator)3.2 线性回归LinearRegression3.3 多项式PolynomialFeatures3.4 工作流Pipeline四、python代码实现4.1 构造模拟信号4.2 编写去除趋势项主代码4.3 展示算法效果五、TIPS 一、概述   在振动测试过程中,传感器或采集设备由于自身性能问题或受环境干扰(如温度、供电等影响),容易

白银时代的博客 8578

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

软考高级-系统架构设计师 论文范文参考(一)

系统架构设计师 论文参考

片言可决讼,半纸能缚龙 4341

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

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

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

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

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

WriteAnything_的博客 1313

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

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、付费专栏及课程。

余额充值