8086のビルドにアセンブリ言語学習(II)8086コンパイル開発環境とデバッグモードを紹介

ビルドに1.8086コンパイル開発環境

  8086アセンブリ言語で簡単なブログ記事で。8086は、8086コンパイル開発環境を構築する方法を説明するために、アセンブリ言語を学び始めた前に私たちは、最初にその利益の必要があります。

  アセンブリ言語は直接なしオペレーティングシステムのベアメタルハードウェアとデザインの初めに使用されているが、ほとんどの人々のために、直接8086のプログラミングベアメタル上の困難のすべての種類に直面するだろう。幸いなことに、我々は8086の研究と実践にハードウェアをシミュレートするシミュレータを使用することができます。著者でWindows環境を通じて「アセンブリ言語」をお勧めしますMASMデバッグ学習。

MASMの説明:

  MASMは 8086でコンパイルDOS、下のツールキットをまとめたものです、我々は、これらのファイルのいくつかを学ぶ必要があるMASM.EXELINK.EXEを

  MASM.EXE アセンブリ言語ソース・ファイルのアセンブラは、バイナリオブジェクトファイルを生成.OBJその端がソースファイルに対応するマシンコードにコンパイルされ、バイナリファイルのテキスト形式.OBJ端にコンパイルされます。別のソースファイルは、通常、ターゲットが直接実行することはできませんが、また同じで、他のバイナリファイルは相互に依存してコンパイル、リンクを(実行ファイルを生成するために一緒に、そのような必要な静的ライブラリなどを)。したがって、OBJファイルは、中間ファイルと呼ばれます。

  LINK.EXE  リンカ、OBJファイルがにリンクすることによって実行可能なプログラムに変換する必要があり、リンカは、このタスクを完了するための責任があります。リンカは、オブジェクトファイルおよびプログラムライブラリ複数のobjをすることができ、それは、均一な処理(例えば、先のファイルの複数の処理命令、データメモリアドレスオフセット)、および実行可能ファイルを生成するに依存します。

デバッグ紹介:

  DEBUG.EXE  デバッガは、ウィンドウは、アセンブラDEBUG.EXE 8086におけるDoSツールをデバッガを提供し、提供、CPUがプログラム実行ディスプレイメモリ内のデータレジスタのそれぞれを命令レベル単一ステップのデバッグ機能を。このブログの後半に詳細に説明するデバッグプログラムを使用します。

64ビットオペレーティングシステムの互換性の問題:

  Windowsシステムが32ビット、32ビットのWindowsシステムでは、デフォルトのMASMとデバッグではインストールされている「アセンブリ言語」以前に出版された本として、DOSウィンドウを直接開くことができます。、デバッグは、Windowsシステムの64ビットバージョンと互換性がありませんMASMながら、しかし、新しいウィンドウの普及64オペレーティングシステムは、それは、デフォルトのMASMキットとDEBUG.EXEを提供していません。

64ビットのWindowsシステムを使用したいMASMを、デバッグ 2つの一般的な方法があります。

  (推奨WindowsはXP)仮想マシンを経由して、Windowsオペレーティングシステムの旧バージョンをインストールします。1.

  シミュレータ軽量MS-DOS 2. DOSBoxを実行、しかし手続きに依存しているが、個別にダウンロード、上記のBaiduのネットワークディスクのダウンロードリンク:https://pan.baidu.com/s/158NKJoea6_Y4UmCFsDP0oQ#リスト/パス=%。2F

  個人的にここで8086アセンブリ言語の開発環境を構築するためにwindows64ビットオペレーティングシステムでDOSBoxをを使用する方法ですが、第二の方法をお勧めします。

インストールと使用DOSBoxを

DOSBoxををダウンロードしてインストールします。

  DOSBoxををすることができます公式サイトダウンロードしてください:また、Baiduのネットワークディスク(バージョン0.74)をダウンロードするためのリンクを提供し、https://pan.baidu.com/s/11_GcPpTqJm78N8xEXZpPMwを

  インストール後、インストールディレクトリ見つけるDOSBox.exeを、以下のような画面を見始めます。

  

  ドスシミュレータと通常のDOS窓として有意な差はありませんが、最初にローカルディスクへの直接アクセスを持っていなかった、あなたはDOSBoxをしてマウントする最初のローカルディスクに必要です

DOSBoxをローカルディスクをマウントするには:

  1.パスとしてディスクをマウントし、ローカル・オペレーティング・システム・ディスク上のフォルダのディレクトリを選択します(たとえば、C:\ DOS)

  2.ファイル名を指定して実行ドスDOSBoxをウィンドウのコマンドの開始:マウントCC:\ DOS(ローカルCの代わりに:\ DOSパスDOSBoxをのCドライブへのパスをマウントする)、Cドライブにウィンドウの作業ディレクトリをDOSすることができます、あなたはマウントされたディスク・パスの内容にアクセスすることができます。

  3.前述DEBUG.EXEおよびその他のファイルをマウントするローカル・ディスク・パスの下に配置されている(例えば、C:\ DOS)は、DOSBoxを介して互換性のMASMツールキットプログラムとDEBUG.EXEを実行することができ

  

重複を避けるために、自動化事業にスクリプトを追加します。

  ディスクをマウントするには、上記のDOSBoxをのためにはDOSBoxをは、あまりにも多くの問題をマウントするため再入力コマンドにする必要があります再起動のたびに、一時的なものです。私たちは、道DOSBoxを構成を変更交換することにより、これらの操作を繰り返すことができます。

  找到DOSBox安装目录下的DOSBox 0.74 Options.bat,使用系统自带的记事本直接打开,暂不研究其它配置段的作用,找到最后的【autoexec】段,配置在【autoexec】的内容会作为命令在DOSBox启动时按顺序被自动执行。  

  将挂载磁盘操作命令配置在【autoexec】段中能避免重复操作。修改并保存配置文件后,重新启动DOSBox,发现配置中添加的命令会被自动执行。

  

2. 8086debug模式介绍

  在搭建好了8086汇编的开发环境后,接下来介绍8086的debug模式。执行debug.exe以进入debug调试模式,在dos中通过输入命令的方式进行交互。

  

  debug模式下有20多种不同命令,限于篇幅这里只会介绍几个以后实验时常用到的命令。(通过回车执行命令,DOS下的命令默认是不区分大小写的)

R命令 查看/改变CPU寄存器内容

  R命令的作用是查看和修改debug模式下CPU中寄存器的值。

  (-r) 单独的输入r,可以查看当前CPU的内容

  (-r 寄存器名) r加上寄存器名可以在接下来的":"提示后输入新的值,以达到修改对应寄存器内容的目的(示例中第二行 AX 0000表示修改前寄存器AX的值为0000)  

D命令 查看内存中的内容

  D命令的作用是查看内存中的内容。

  D命令有许多不同的传参方式可供使用,先介绍最易理解的(段地址:偏移地址)查看方式。D命令默认会显示寻址地址开始的后128个内存单元的内容,以16进制的方式显示(每个内存单元8位,一行最多16个内存单元),而最右边会将内存单元中的二进制数据以ascll码的形式翻译展示。

  

  有时,我们只想聚焦于某一部分内存地址的内容,而默认展示的内存视图不是很方便。

  D命令提供了另外一种访问内存的方式(段地址:偏移起始地址 偏移终止地址),其能够展示(段地址:偏移起始地址 至 段地址:偏移终止地址)的内存信息,范围两端均为闭区间。

  

E命令 改变内存中的内容

  E命令的作用是改变内存中的内容

  和对CPU中寄存器的查看,修改不同,对内存进行查看和修改较为复杂,为此debug设计了两个不同的命令分别进行控制(E命令修改内存、D命令查看内存)。

  通过(E 起始地址 数据1 数据2 数据3...)命令可以修改内存中以起始地址开始,顺序的N个内存单元的值(N为实际参数传递的数量)。

  

   也可以和R命令修改CPU中寄存器值类似的,通过提示来修改特定内存单元的值。00.12  00代表内存单元在修改前的值,12是我们手动输入的、需要修改的新值。

  

  可以通过E命令向内存输入对应的机器指令,因为机器指令也是数据的一种

有以下指令(左侧为机器码,右侧为对应的汇编指令):

  B80100  mov ax,0001

  BB0200  mov bx,0002

  01D8      add ax,bx

  我们可以向内存1000:0处写入这些机器指令,以供接下来通过debug执行这段机器指令 (执行命令:E 1000:0 B8 01 00 BB 02 00 01 D8)。

  

U命令 将内存数据转换为汇编指令展示

  U命令的作用是将内存中的二进制数据转换为汇编指令展示(反汇编)。

  D命令能够将内存中的数据以16进制或ascll码的形式展现出来,但有时我们需要观察的是内存中的机器指令时,D命令的视图过于抽象,不利于理解。debug提供了U命令来解决这个问题。

  对于前面我们在1000:0处输入的机器指令,使用 U 1000:0 命令(u 内存地址)可以将内存中的数据以汇编语言指令的方式进行展示。

  

  可以观察到,左边展示的是内存地址,中间则是16进制的内存视图,右边展示的是内存中数据所对应的汇编指令(例如: 1000:0000B80100MOV AX,0001)。

  由于我们只输入了三条汇编指令,而后面内存中的数据并不是我们想要执行的,但U命令却依然将其以汇编指令的形式转换并显示出来了。

  这也是前一篇博客所提到的,内存中的数据完全是二进制的,既可以将其看做普通的二进制数据、十六进制数据、ascll码文本数据,也可以视作程序指令,这些二进制的"数据"的处理完全取决于如何对其进行解释

T命令 单步执行机器指令

  T命令的作用是进行单步机器指令的调试

  以上文通过E命令写入内存1000:0的三条指令举例,介绍如何使用T命令来让CPU执行1000:0处的机器指令。T命令用于单步调试,一次只会执行一条机器指令。

  8086CPU在运行时会将CS:IP寄存器所指向的内存单元中的内容解释为指令执行,要将内存1000:0处的内容作为指令执行必须先修改CS、IP两个寄存器的值,使之指向1000:0。

  

   先执行一次T命令,1000:0处的指令(mov ax,0001)便会被执行,可以观察到寄存器ax的值已经变成了0001;同时寄存器IP的值增加了3(mov ax,0001的指令长度为3),此时CS:IP指向的便是位于1000:3处的下一条指令(mov bx,0002),在视图的最后一行中也有所体现

   

   再执行一次T命令,会执行1000:3处的指令(mov bx,0002),可以观察到寄存器bx的值变成了0002;寄存器IP的值又增加了3(mov bx,0002的指令长度也是3),此时CS:IP指向的便是位于1000:6处的下一条指令(add ax,bx)

  

  最后执行一次T命令,add ax,bx会被执行(类似 ax=ax+bx)。寄存器ax的值已经变成了之前寄存器ax和bx中的数据之和0003;寄存器IP的值增加了2(add ax,bx的指令长度是2),CS:IP指向1000:8。

  

A命令 以汇编指令的形式向内存中写入内容

  A命令能够以汇编指令的形式向内存中写入内容

  对于内存操作,D命令可以查看内存中的内容,但如果想查看的是程序指令,显然U命令更加方便;E命令可以向内存中写入数据,但对于程序指令的写入,直接操作二进制机器码的方式过于硬核。为此,debug提供了A命令,我们可以通过A命令以汇编指令的形式向内存中写入内容。

  通过A命令将(mov ax,0001,mov bx,0002,add ax,bx)三条指令写入内存1000:0处:

  

  通过A命令进行指令的写入,和E命令达到的效果一样,但使用起来却更加便捷。A命令能够自动识别所输入汇编指令的长度,正确的在内存中写入程序指令。

  debug提供了D、E两种命令用于对内存进行通用的操作(纯二进制、十六进制数据的读、写)。

  对于程序指令,debug提供了U、A两种命令以更人性化的方式来读写内存中的指令内容。

三 总结

  在debug模式下可以模拟8086汇编非常自由的控制CPU和内存,这也是汇编语言的强大之处和魅力所在。

贴近硬件底层的编程能够让我们编写出来的程序非常高效,但也存在一些问题:

  1.内存中的内容被当做指令还是数据来处理完全取决于如何解释,编程时稍有不慎就会导致CPU执行一些不应该执行的指令,甚至造成巨大的破坏。

  2.在未来还会介绍如何使用汇编语言来实现高级语言中出现的结构体、数组等概念。这些数据结构完全是程序逻辑上的,内存本身可没有这些功能。因此在使用汇编访问内存中结构化的数据时,一不小心就会出现内存访问越界,错位等问题。

  3.汇编语言的抽象程度过低,许多在高级语言中很简单的功能在汇编中也需要很多的代码来实现(汇编实现的控制台打印hello world可能是常用语言中最繁琐的了)。

  编程语言的贴近底层与机器高效性如果站在更高的角度上看其实是一把双刃剑:直接操控底层的机器方便,机器执行效率高的同时,也是危险、开发效率底下的。汇编语言程序员不得不付出巨大的精力来仔细思考、斟酌这些底层机器层面的细节,以避免出现相关bug,大大降低了开发效率。这也是高级语言诞生,并不断发展的主要原因。

  高级语言大家族中按抽象程度来看,从偏底层的C,C++到java、python等,再到目前抽象程度最高的lisp。随着抽象程度的提高,离机器底层越远,执行效率通常也随之降低。但程序员所需要考虑的机器细节也就越少,能更专注于业务逻辑,进而提高了开发效率。比如在使用C编程时还需要仔细考虑指针错误,堆上无用内存回收等问题,到了更高级的java、python中,这些问题都交由编译器、虚拟机解决了,对开发人员也几乎透明了。

  天下没有免费的午餐,在选择适合的编程语言开发程序时,需要在机器执行效率和开发效率间做出取舍。但随着科学技术的发展,计算机硬件会越来越强大,对机器效率的担忧会越来越少,对程序开发效率的考虑将占据主导地位,越来越多的程序将会倾向于使用抽象程度更高的编程语言进行开发。

  虽然需要使用汇编语言的场合越来越少,但对汇编语言和底层机器硬件有一定的了解的话,依然能够帮助程序员更深刻的理解上层的知识内容、写出更高效的程序。

  毕竟,人类是无法抽象、封装到完美无缺的,有时还是你需要跳进下水道,深入底层一探究竟的。

  

おすすめ

転載: www.cnblogs.com/xiaoxiongcanguan/p/12176857.html