8086-2-搭建直接通过CPU执行汇编语言的环境
<h1 class="md-end-block md-heading md-focus"><span class="md-plain md-expand">搭建直接通过CPU执行汇编语言环境</span></h1><p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">我们通过编译写好的汇编语言代码可以生成.bin的机器语言二进制代码。但是这个.bin程序我们该如何运行呢?</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">这里其实有两个办法:</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">1:<span class="md-tab"> <span class="md-plain">将其作为一个Windows/linux也就是操作系统的可执行程序来运行,这个nasm是可以做到的,很多工具也可以做到,把一个汇编程序编译链接成一个.exe来处理。</span></span></span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">2:<span class="md-tab"> <span class="md-plain">直接通过CPU来使用。因为.bin文件是机器码,肯定是可以直接让CPU来使用的。操作系统也是一个需要在处理器上运行的软件,只不过比 起一般的程序而言,体积更为庞大,功能更为复杂而已。如果我们能绕过它,或者代替它,让计算机一开机的时候直接执行我们自己的程序, 岂不更简单?<span class="md-pair-s"><strong>而且很酷,不用操作系统,自己直接操作CPU。</strong></span></span></span></span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-pair-s"><strong>采用第一种比较简单,这里就不详述了。</strong></span></span></p>
<h2 class="md-end-block md-heading"><span class="md-plain">搭建环境原理:</span></h2>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">前面我们讲述了8086的启动操作:</span></span></p>
<p class="md-end-block md-p"><span class="md-meta-i-c md-link"><span class="md-plain">计算机的启动过程(8086) - Sna1lGo - 博客园 (cnblogs.com)</span></span></p>
<p class="md-end-block md-p"> </p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">在bios调用完之后cs:ip会变成物理地址0x07C00来加载主引导扇区的代码,我们可以直接通过硬盘启动,然后把硬盘的主引导扇区的代码变成我们自己的代码。这多帅,直接操作CPU,避开操作系统。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">但是我们还需要有调试功能才行,因为如果不能调试,那么CPU就直接顺着代码走就完了,我们啥也看不到,所以我们需要一个带有调试功能的虚拟机。正好有一个非常适合我们,叫做 bochs:<span class="md-meta-i-c md-link"><span class="md-plain">bochs: The Open Source IA-32 Emulation Project (Home Page) (sourceforge.io)</span></span></span></span></p>
<p class="md-end-block md-p"> </p>
<h2 class="md-end-block md-heading"><span class="md-plain">预备知识</span></h2>
<h3 class="md-end-block md-heading"><span class="md-plain">虚拟硬盘简介:</span></h3>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">我们把我们的代码写到硬盘里,然后虚拟机读取我们的硬盘就行了。但是由于我们得往硬盘里写东西,所以需要提前了解一下硬盘。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">虚拟硬盘并不是真实的硬盘,而是用文件来模拟生成的一个硬盘。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">虚拟硬盘有很多这里介绍三个:</span></span></p>
<table class="md-table">
<thead>
<tr class="md-end-block"><th><span class="td-span"><span class="md-plain">VMDK</span></span></th><th><span class="td-span"><span class="md-plain">VMWare虚拟机</span></span></th></tr>
</thead>
<tbody>
<tr class="md-end-block">
<td><span class="td-span"><span class="md-plain">VDI</span></span></td>
<td><span class="td-span"><span class="md-plain">VirtualBox虚拟机</span></span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span"><span class="md-plain">VHD</span></span></td>
<td><span class="td-span"><span class="md-plain">Virtual-PC/Hyper-V虚拟机</span></span></td>
</tr>
</tbody>
</table>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">其中VHD比较简单,所以这里我们就采用VHD虚拟硬盘。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">VHD也可以分为固定尺寸和动态尺寸,其中固定尺寸更简单,所以采用VHD的固定尺寸硬盘。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">在VHD 规范里,<span class="md-pair-s "><strong>每个扇区是512 字节</strong><span class="md-plain">。VHD文件一开始的512 字节,就对应着物理硬盘的0 面0 道1 扇区。然后,VHD 文件的第二个512 字节,对应着0 面0 道2 扇区,后面的以此类推。再往后,因为硬盘的访问是按柱面进行的,所以,下一个数据块对应的是1 面0 道1 扇区,就这样一 直往后排列,当把第一个柱面全部对应完后,再从第二个柱面开始对应。<span class="md-pair-s"><strong>磁盘转圈比移动快,所以最后才移动磁道。</strong></span></span></span></span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">固定尺寸的VHD 虚拟硬盘 是一个具有“.vhd”扩展名的文件,它仅包括两个部分,前面是数据区,用来模拟实际的硬盘空间,最后面跟着一个512 字节的结尾</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">文件尾的内容是以一个字符串“conectix”开始的。这个标志用来告诉试图打开它的虚拟机,这的确是一个合法的VHD 文件。该标志称为VHD 创建者标识,就是说,该公司(conectix)创建了VHD 文 件格式的最初标准:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223454212-850785999.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">从这个标志字符串开始,后面的数据包含了诸如文件的创建日期、VHD 的 版本、创建该文件的应用程序名称和版本、创建该文件的应用程序所属 的操作系统、该虚拟硬盘的参数(磁头数、每面磁道数、每磁道扇区 数)、VHD 类型(固定尺寸还是动态增长)、虚拟硬盘容量等。</p>
<h3 class="md-end-block md-heading"><span class="md-plain">磁盘的访问逻辑:</span></h3>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">传统的访问模式就是:CHS,通过柱面磁道磁头,也就是前面的0 面0 道1 扇区这种类似的格式,但是这个不太方便。</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223502011-8873537.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">然后就有了LBA(Logical Block Address)就是把所有的扇区进行一个逻辑编号,从0开始到最后一个扇区进行编号,然后单位为块(block)其实就是扇区,只不过扇区看着确实是一块一块的:</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223514706-638724481.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">LBA和CHS的对应方式:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223523435-1399128901.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">存储容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数</p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">移动方式稍微不一样点,先移动扇区再磁头最后再更改柱面。<span class="md-pair-s "><strong>因为更改柱面磁头需要移动。</strong><span class="md-plain"> 也就是以柱面为单位来读取的意思。</span></span></span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">LBA = 磁道*磁头 *每个磁道的扇区数+ 磁头 * 每个磁道的扇区数 + 扇区位置-1</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">比如这里的: 1面0道2扇区 == 0* 2*17 + 1 *17 +2 -1 ==18</span></span></p>
<p class="md-end-block md-p"><span class="md-plain"> 0面1道2扇区 == 1*2 *17 +2 -1 == 35</span></p>
<p class="md-end-block md-p"> </p>
<h2 class="md-end-block md-heading"><span class="md-plain">需要工具:</span></h2>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">安装bochs:(在这里选择自己的需要的版本)</span></span></p>
<p class="md-end-block md-p"><span class="md-meta-i-c md-link"><span class="md-plain">Bochs x86 PC emulator - Browse /bochs/2.7 at SourceForge.net</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">安装 VirtualBox:</span></span></p>
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">Downloads – Oracle VM VirtualBox</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">下载李忠老师的软件包:</span></span></p>
<p class="md-end-block md-p"><span class="md-link md-pair-s">http://www.lizhongc.com/myfiles/download.php?id=201</span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">下载二进制查看软件:</span></span></p>
<p class="md-end-block md-p"><span class="md-meta-i-c md-link"><span class="md-plain">Download HexView 2.0 (softpedia.com)</span></span></p>
<p class="md-end-block md-p"> </p>
<h2 class="md-end-block md-heading"><span class="md-plain">搭建环境</span></h2>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">创建一个固定尺寸的VHD虚拟硬盘,然后将其安装到Bochs虚拟机上。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">第一步创建一个虚拟硬盘:</span></span></p>
<h3 class="md-end-block md-heading"><span class="md-plain">创建虚拟硬盘:</span></h3>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">1:打开Virtual Box,单击管理—>虚拟介质管理器,就会得到这个界面:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223535382-1893722133.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">2:点击创建,选择VHD虚拟硬盘:</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223542808-596386825.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">3:选择固定大小:</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223552206-1807506858.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">4:自己选择硬盘位置和大小(我这里拿来学习所以不需要太大)</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223601884-892956540.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">5:查看结果</p>
<p class="md-end-block md-p"><span style="font-size: 1.17em"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223609936-1447007060.png"></span></p>
<p> </p>
<p class="md-end-block md-p"><span style="font-size: 1.17em"></span></p>
<p> </p>
<p class="md-end-block md-p"><span style="font-size: 1.17em">配置bochs环境</span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">1:选中配置:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223624354-33932177.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">2:关闭软盘:(软盘基本上绝迹了)</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223634910-696372556.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">3:选中ATA channel0:(这个就默认值不改就好)</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223644272-562439063.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">4:选中ATA channel0的子目录 First HD/CD on channel0</p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">然后修改,其中Path开头那个是前面创建的虚拟硬盘。</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223653646-114800071.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">然后剩下的信息需要查看虚拟磁盘的信息才可以,这里要用到前面李忠老师的资源包里的一个软件:</p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">叫做fixvhdwr.exe,用它来打开我们前面创建的虚拟硬盘</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223705833-1611108030.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">然后根据里面的信息来填充到前面:</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223714920-893318158.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223723957-1881562238.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">Cylinders为柱面,Heads为磁头,Sectors per track为每个磁道有多少扇区。</p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">5:修改计算机的启动顺序:</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">改成第一个用磁盘,第二个用光盘。</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223731634-1949739311.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p"> </p>
<h2 class="md-end-block md-heading"><span class="md-plain">编写程序放到主引导扇区,让计算机在启动后执行:</span></h2>
<h3 class="md-end-block md-heading"><span class="md-plain">编译程序:</span></h3>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain"> 首先先采用汇编语言来简单编写一个程序:</span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-keyword">mov <span class="cm-variable">ax,0x30<br><span><span class="cm-keyword">mov <span class="cm-variable">dx,0xc0<br><span><span class="cm-keyword">add <span class="cm-variable">ax,<span class="cm-variable">dx</span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">然后将其编译成.bin二进制文件:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223740015-1938101450.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">不知道这一步怎么处理的可以查看我的一篇博客:</p>
<p class="md-end-block md-p"><span class="md-meta-i-c md-link"><span class="md-plain">搭建一键化编译汇编语言的环境 - Sna1lGo - 博客园 (cnblogs.com)</span></span></p>
<p class="md-end-block md-p"> </p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">然后采用前面下载的二进制查看文件HexView来打开我们的.bin文件:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223748124-1978274519.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">可以看到我们这个只有8个字节的内容,但是扇区是以512个字节为单位的,所以我们必须填充成512个字节才行。而且主引导扇区的结尾必须是16进制的55和AA不然就是无效的。</p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">所以我们还得修改一下汇编代码:</span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-keyword">mov <span class="cm-variable">ax,0x30<br><span><span class="cm-keyword">mov <span class="cm-variable">dx,0xc0<br><span><span class="cm-keyword">add <span class="cm-variable">ax,<span class="cm-variable">dx<br><span><span><br><span><span class="cm-keyword">times <span class="cm-keyword">502 <span class="cm-keyword">db <span class="cm-keyword">0x0 <br><span><span><br><span><span class="cm-keyword">db <span class="cm-keyword">0x55 <br><span><span class="cm-keyword">db <span class="cm-keyword">0xAA</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">这里的times 502 db 0x0 相当于填充了502个字节的内容且为0。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">然后最后结尾为0x55和0xAA。</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">来查看一下编译后的结果:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223756264-441478345.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">一共是512个字节(0x200),且结尾为0x55和0xAA。</p>
<h3 class="md-end-block md-heading"><span class="md-plain">将程序写入到虚拟硬盘:</span></h3>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">这里需要用到李忠老师提供的软件包的一个软件:fixvhdwr.exe</span></span></p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">这个只能写入固定硬盘的内容:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223812477-379971201.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">选中我们刚刚的编译好的二进制.bin文件。</p>
<p class="md-end-block md-p"><span class="md-tab"> <span class="md-plain">然后选择LBA,前面我们了解了LBA的知识所以第一个扇区0面0道1扇区就等于 LBA的0,这里就选0然后选择写入就好了:</span></span></p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223820821-2121554665.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">然后采用二进制查看工具,查看我们写入了的VHD磁盘是否成功:</p>
<p class="md-end-block md-p"><img src="https://img2020.cnblogs.com/blog/1940490/202112/1940490-20211215223830709-1288933910.png"></p>
<p> </p>
<p> </p>
<p class="md-end-block md-p">前0x200个字节完全对应,所以是成功了。</p><br><br>
来源:https://www.cnblogs.com/Sna1lGo/p/15695712.html
頁:
[1]