使用bochs调试汇编程序

前面我们已经搭建好了bochs的环境,并且将我们的汇编程序写入了硬盘里面,现在我们来看看如何通过bochs来调试我们的程序。

前文:https://www.cnblogs.com/Sna1lGo/p/15695712.html

bochs安装文件夹

安装完bochs后,在安装目录下我们可以看到有两个.exe可执行程序:

bochs.exe就和正常的安装的虚拟机一样了,就是直接运行了。

而bochsdbg.exe才是我们要的可调试的虚拟机。

同时可以看到这个文件夹下面有一个docs文件夹,里面包含了bocsh的一些手册,感兴趣的可以读一下。

进行bochsdbg调试:

首先要启动bochsdbg虚拟机:

然后得添加配置文件,前面的章节我们是添加了配置的,但是如果你没保存,那么很不幸你得再来一次了,需要注意的是保存的配置文件千万不要修改配置文件的名字。这里由于我保存了的我就直接start了。

加载后是这样一个界面:

左边的display就类似于显示器了,然后右边的就是命令行调试窗口,启动后命令行调试窗口前面显示的是一系列虚拟机的状态信息。

bochs会在执行第一条指令的时候停下来,等待我们的操作,也就是这里的命令行调试界面:

bochs的调试指令可以看bochs的官方文档上看到:

The Bochs internal debugger (sourceforge.io)

当然它也包含在了我们安装bochs文件夹的docs文件夹下面。

Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b         ; ea5be000f0

0x0000fffffff0 代表真实的物理地址

f000:fff0 是逻辑地址

jmpf 0xf000:e05b 是汇编指令

ea5be000f0 是机器指令

Next at t=0 中的t是执行的指令个数,也叫做内部时钟

注:细心的朋友可能会发现,这里的f000:fff0的逻辑运算是无法计算得到0x0000fffffff0地址的,这个只会在处理器刚启动的时候发生,然后后面会解释,这里先暂时就这个样子。

肯定有同学会奇怪啊,前面我们说了8086启动的第一条指令是jmp FFFF:0000啊,这里怎么不一样,那说明这个cpu不是8086呀。哈哈。

我们把这个调试界面往前翻一下,查看前面的状态信息可以看到:

这里的CPU configuration也就是CPU的配置信息是x86-64的,是intel的支持x86的CPU并不是8086CPU。

这里我们可以先单步执行看看内容,这里是所有的执行指令:

  c                           continue executing
cont
continue

s     [count]               execute count instructions, default is 1
step [count]

s     [cpu] [count]         for SMP simulation, execute count instructions on cpu, default is 1
step [cpu] [count]

s     all [count]           for SMP simulation, execute count instructions on all cpus
step all [count]

Ctrl-C                      stop execution, and return to command line prompt
Ctrl-D                      if at empty line on command line, exit

q                           quit debugger and execution
quit
 exit

可以采用s来单步执行,默认是只执行一条,就到了这里:

可以看到这个地址区域,是满足前面我们将的cpu地址分区的BIOS地址区域的在F0000~FFFFF之间。

那么如果我们想直接到我们写的主引导扇区里面怎么办呢,我们可以给主引导扇区的第一条代码打一个断点,这里是所有的断点指令:

NOTE: The format of 'seg', 'off', and 'addr' in these descriptions,
      are as follows. I don't have any way to set the current radix.

      hexidecimal:   0xcdef0123
      decimal:        123456789
      octal:          01234567

vbreak seg:off             Set a virtual address instruction breakpoint
vb     seg:off

vbreak seg:off if "expr"   Set a conditional virtual address instruction breakpoint
vb     seg:off if "expr"

lbreak addr                 Set a linear address instruction breakpoint
lb     addr

lbreak addr if "expr"       Set a conditional linear address instruction breakpoint
lb     addr if "expr"

pbreak [*] addr             Set a physical address instruction breakpoint
pb     [*] addr             (the '*' is optional for GDB compatibility)
break [*] addr
b     [*] addr

pbreak [*] addr if "expr"   Set a conditional physical address instruction breakpoint
pb     [*] addr if "expr"   (the '*' is optional for GDB compatibility)
break [*] addr if "expr"
b     [*] addr if "expr"

info break                 Display state of all current breakpoints
bpe   n                   Enable a breakpoint
bpd   n                   Disable a breakpoint
delete n                   Delete a breakpoint
del   n
d     n

那么打断点肯定是不能像vs调试一样直接给代码打上断点然后直接调试就完事了,在cpu的层面是直接给地址打断点,执行到该处就直接停下来。前面的博客我们学习到,CPU会把主引导扇区的内容加载到内存的 0000:7c00处,那么我们直接给这个地址打个断点然后运行到这个地址就停下来不就行了吗。

b 0x7c00

解释一下这条命令,上面我写了所有的断点指令,然后单独的 b 后面是跟着addr,然后逻辑地址的0000:7c00就是物理地址的 7c00,所以我这样使用是没问题的。

然后我们可以输入执行指令,来直接执行到设置的断点处:

这里就是我们前面写好的汇编代码了。

然后采用s指令单步调试来把我们的代码都执行完:

好这里就执行完了,然后可以查看一下寄存器,看看ax,dx是不是我们设想的内容。

以下是查看bochs虚拟机信息的所有指令:

  r|reg|regs|registers         List of CPU integer registers and their contents
fp|fpu                       List of all FPU registers and their contents
mmx                         List of all MMX registers and their contents
sse|xmm                     List of all SSE registers and their contents
ymm                         List of all AVX registers and their contents
sreg                         Show segment registers and their contents
dreg                         Show debug registers and their contents
creg                         Show control registers and their contents

info cpu                     List of all CPU registers and their contents
info eflags                 Show decoded EFLAGS register
info break                   Information about current breakpoint status
info tab                     Show paging address translation
info device                 Show state of the specified device

可以看到ax和dx确实是我们想要的内容,0x00F0和0x00c0。

这样就很完美了。

 

由于我们这次写的汇编代码很简单,所以就这么几条就执行完了。

可以使用退出指令来直接退出该bochs虚拟机了:

q                           quit debugger and execution
quit
exit

这样摁完Enter回车就可以美美哒结束了。

小结

采用原原本本的通过cpu来执行汇编代码的方式虽然比较繁琐,但是逼格很高,哈哈,至少我是这样认为的。

总结一下流程:

先写好汇编代码,然后编译,编译好之后,和512个字节进行比对,不够的要填充,填充的时候注意最后两个字节的内容必须为55和AA,然后将其写入硬盘里。再启动bochs虚拟机给系统主引导扇区的地址打断点,然后执行continue运行,会停止到断点处,就可以进行对我们自己的汇编语言代码进行调试了。而且是绕过了Windows\linux这样的大型操作系统,这多酷。然后如果调试遇到指令问题就查看bochs的文档就可以了。

使用bochs调试汇编程序的更多相关文章

  1. 用bochs调试自己写的系统引导代码

    1 安装和配置bochs 首先从bochs.sourceforge.net里面把BOCHS给download下来,鉴于Windows的普及,仅仅谈BOCHS在win下的使用方法,其实在其它的OS中方法 ...

  2. 利用bochs调试Linux 0.11内核

    引导程序调试软件bochs,跟配套的linux0.11内核img下载地址分别是: http://sourceforge.net/projects/bochs/http://www.oldlinux.o ...

  3. bochs 调试 com 文件 magicbreak

    参考 https://blog.csdn.net/housansan/article/details/41833581 在网上看到2中解决此问题的方法:1.使用dos下的debug32工具单步跟踪pm ...

  4. bochs调试命令

    Bochs几条基本指令: 通过物理地址查看内存时,可以不加参数'/nuf': 其中n指定显示的单元数,默认是1: u 指定每个显示单元的大小(b表示字节.h表示字(2字节).w表示双字(4字节)),默 ...

  5. Bochs调试加载符号文件的问题

    1. Bochs中的调试命令ldsym没有触发的情况. 参考:http://www.ibm.com/developerworks/cn/linux/sdk/lex/ Lex 代表 Lexical An ...

  6. 如何制作一个可以用Bochs调试的最新内核系统盘

    参考:http://blog.chinaunix.net/uid-26207112-id-3332621.html 1. 正确地创建一个包含启动分区的磁盘映像 1.1 创建磁盘映像文件 首先需要对磁盘 ...

  7. Bochs调试VirtualBox生成的VDI映像

    将VDI映像转换成Bochs支持的img映像 1: vboxmanage clonehd source.vdi destination.img --format RAW 在bochsrc.txt中引用 ...

  8. GDB结合Bochs调试内核

    1. 编译内核 编辑.config文件,相关项目改成如下形式: 1: CONFIG_KGDB=y 2: CONFIG_KGDB_SERIAL_CONSOLE=y 3: CONFIG_MAGIC_SYS ...

  9. VS2010调试X86汇编程序

    今天突然无聊了一下,想起之前想的用VS来调试汇编程序.之前只是想了一下,没有去做,好吧,今天搜索一下,找到了一个教程,相当的详细具体,我喜欢 按照http://blog.csdn.net/jinson ...

随机推荐

  1. [atAGC045F]Division into Multiples

    令$d=\gcd(a,b)$,可以发现$c|(ax+by)$等价于$lcm(c,d)|(ax+by)$,因此不妨令$c'=lcm(c,d)$,然后将$a$.$b$和$c$同时除以$d$ 接下来设$(a ...

  2. 基于echarts 24种数据可视化展示,填充数据就可用,动手能力强的还可以DIY(演示地址+下载地址)

    前言 我们先跟随百度百科了解一下什么是"数据可视化 [1]". 数据可视化,是关于数据视觉表现形式的科学技术研究. 其中,这种数据的视觉表现形式被定义为,一种以某种概要形式抽提出来 ...

  3. 查询某个信息下只有一条数据的sql

  4. [IIS]发布到 IIS 上的程序没有权限访问共享文件

    老板突然跑路了,丢下一个破项目让我一个人维护,各种奇葩问题不断. 为了弄一键发布,布置了新的环境,结果新环境下的程序不能访问共享文件了. 访问共享文件需要设置应用程序池(Application Poo ...

  5. Windows快捷键及cmd打开方式

    Windows快捷键 win+e 打开我的电脑 win+r 打开运行 ctrl+z 撤销 shift+del 彻底删除 alt+F4 关闭窗口 ctrl+c 复制 ctrl+a 全选 ctrl+x 剪 ...

  6. Django创建多对多表关系的三种方式

    方式一:全自动(不推荐) 优点:django orm会自动创建第三张表 缺点:只会创建两个表的关系字段,不会再额外添加字段,可扩展性差 class Book(models.Model): # ... ...

  7. 02 Windows安装C语言开发工具CodeBlocks

    CodeBlocks安装 使用微信扫码关注微信公众号,并回复:"C语言环境",免费获取下载链接! 1.卸载CodeBlocks(电脑未装此软件,跳过)    进入目录:C:\Pro ...

  8. Pytorch学习笔记08----优化器算法Optimizer详解(SGD、Adam)

    1.优化器算法简述 首先来看一下梯度下降最常见的三种变形 BGD,SGD,MBGD,这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度,这样的话自然就涉及到一个 trade-off,即参数更 ...

  9. R语言学习记录(二)

    4.对象改值 4.1.就地改值 比如: vec <- c(0,0,0,0,0,0,0) vec[1]<-100 #vec向量的第一个值就变为100 ####对于数据框的改值的方法,如下面的 ...

  10. 零基础学习java------day5------do....while循环、嵌套、方法(函数)

    1  do...while循环 格式 初始化语句; do { 循环体语句; 控制条件语句; }while(判断条件语句); 流程: 先执行初始化语句 再执行循环体语句 再执行条件控制语句 再做条件的判 ...