编译器

可以将汇编指令转换成机器指令的翻译程序

程序员 –> 汇编指令 –> 编译器 –> 机器码 –> 计算机


指令和数据

指令和数据其实是应用上的概念。在内存或磁盘上,指令和数据没有任何的区别,都是以二进制信息的形式存储

  • 例如,内存中的二进制信息:1000100111011000
    1. 可以看成大小为 89D8h 的数据来处理
    2. 可以看成是指令 mov ax, bx 来执行

存储单元

存储器被划分为若干个单元,每个存储单元从 0 开始顺序编号

  • 微型机存储器的容量以 字节 (Byte) 作为最小单位
    1. 1 个字节 (Byte) = 8 个比特 (bit)
    2. 例如,一个存储器有 128 个存储单元,则它可以存储 128 个字节 (Byte)

x86汇编_基础知识1.png

1 KB = 1024 B
1 MB = 1204 KB
1 GB = 1024 MB
1 TB = 1024 GB


CPU 对数据的读写

CPU 想要进行数据读写,需要三类信息:

  1. 存储单元的地址(地址信息) —— 地址总线
  2. 器件的选择、读或写的命令(控制信息) —— 控制总线
  3. 读或写的数据(数据信息) —— 数据总线
  • 示例:CPU 从 3 号内存单元中读取数据的过程

x86汇编_CPU对数据的读写1.png


地址总线

CPU 是通过地址总线来指定内存单元的

地址总线上能传送多少个不同的信息,CPU 就能对多少个内存单元进行寻址

  • 若一个 CPU 有 N 根地址线,则可以说这个 CPU 的地址总线宽度为 N,最多可以寻址 $2 ^ {N}$ 个内存单元

  • 示例:地址总线为 10 根的 CPU 向内存发出地址信息 11

x86汇编_地址总线1.png


数据总线

实现 CPU 与内存或其他器件之间的数据传送

数据总线的宽度决定了 CPU 和外界的数据传送速度

  • 8 根数据总线一次可以传输 8bit 二进制数据(一个字节)

  • 示例:当 CPU 向内存写入数据 89DF8h

x86汇编_数据总线1.png

  1. 8086CPU 地址总线为 16 位,可以一次传输 16bit 数据,因此 89D8h 可以一次传输完成

  2. 如果是 8088CPU 的话,地址总线只有 8 位,一次就只能传输 8bit,因此需要传输两次,先传送 D8h,再传送 89h


控制总线

实现 CPU 对外部器件的控制

有多少根控制总线,就意味着 CPU 提供了多少种对外部器件的控制


搭建 DOSBox debug 环境

下载 DOSBox:Download DOSBox0.74-3-win32-installer.exe (DOSBox) (sourceforge.net)

双击安装

在 DOSBox 的安装目录下双击 DOSBox 0.74-3 Options.bat 文件,弹出 dosbox-0.74-3.conf 文件

x86汇编_DOSBox环境搭建1.png

dosbox-0.74-3.conf 的最后,加上下面两句 (尽量不要加中文注释,否则打开 DOSBox 会报错,无法进入到指定文件夹):

mount c d:\masm
c:

这两句的意思是:
将本机的 d:\masm 作为 DOSBox 环境的 C 盘,并进入到 DOSBox 的 C 盘目录下 (作为 DOSBox 环境 C 盘的 d:\masm 目录可自己设定,尽量不要有中文)

保存后,打开 DOSBox,显示本地目录被成功挂载为 C 盘

x86汇编_DOSBox环境搭建2.png

另外,DOSBox 默认的运行窗口特别小,字体也很小

可以通过 dosbox-0.74-3.conf 自定义窗口尺寸,找到如下位置: (大概在 29 行)

windowresolution=original
output=surface

修改为:

windowresolution=1024x768
output=opengl

重新打开 DOSBox:

x86汇编_DOSBox环境搭建4.png

然后还需要下载汇编、链接程序

下载地址:DOSBox 编译链接相关程序

x86汇编_DOSBox环境搭建3.png

主要是 MASM.EXELINK.EXEDEBUG.EXEML.EXEMASM.EXE + LINK.EXE

MASM.EXE:汇编程序,用于汇编源程序 .asm,得到目标程序 .obj
LINK.EXE:链接程序,用于链接目标程序,得到可执行程序 .exe
DEBUG.EXE:调试程序,用于调试可执行程序


搭建 VScode debug 环境

VScode 提供了 MASM 和 DOSBox 环境的插件,并且 VScode 本身也是一款十分出色的编辑器,提供了各种语法高亮,可以很方便的搭建 debug 环境

打开 VScode 中的扩展栏,搜索 masm,找到 MASM/TASM 这个插件,安装

x86汇编_搭建VScode debug环境1.png

这个插件会将 DOSBox 以及汇编编译器 MASM 都安装好,也不需要我们再去挂载之类的操作了

写完代码后,直接右键运行或者调试

x86汇编_搭建VScode debug环境2.png


常用的 debug 指令

参数意义
r查看、更改 cpu 寄存器内容
d查看内存中内容
e改写内存中内容
u将内存中机器指令翻译成汇编指令
a以汇编格式在内存中写入一条指令
t单步执行,一次只执行一条机器指令
p类似 t 命令,不过遇到子程序调用的时候不会进入子程序逐条执行,而是直接执行完子程序代码。另外,在遇到 loop 循环指令时,会直接执行到 CX=0
g该命令后面可以跟地址和断点,格式为:g [=address] [breakpoints],运行到内存指定位置的代码后暂停,如果不加参数默认是从当前 IP 运行到程序结束。可以用来跳过 loop 循环
q退出 debug

r 命令

  1. 输入 r 后回车,会显示所有寄存器的数值

x86汇编_r命令1.png

  1. 输入 r ax 后回车,会显示当前 ax 中的数据,在 ':' 后面输入内容后回车,即可修改 ax 的数据(十六进制)

x86汇编_r命令2.png


d 命令

  1. 输入 d 后回车,显示内存数据,区域地址为上次查看的位置继续往后的内存数据

x86汇编_d命令1.png

  1. 输入 d 1000:00 后回车,显示段地址为 1000,偏移地址为 0 的内存数据

x86汇编_d命令2.png

  1. 输入 d 1000:00 ff 后回车,显示段地址为 1000,偏移地址为 0 到 ff 的内存数据

x86汇编_d命令3.png


e 命令

  1. 输入 e 1000:00 23 11 22 66 后回车,可以一次性修改段地址为 1000,偏移地址为 0 的 4 个数据的值为 23、11、22、66(数据的个数自己可以随意选择)

x86汇编_e命令1.png

  1. 输入 e 1000:00 后回车,可以根据提示按地址顺序一个一个修改数据的值。'.' 前面的数表示原来的数据,在 '.' 后面输入修改后的数据,然后按空格继续修改下一个地址的数据,最后按回车结束修改,例如修改为 1、2、3、4

x86汇编_e命令2.png


u 命令

  1. 输入 u 后回车,可以将上次查看的区域地址位置继续往后的内存地址上的机器码翻译为汇编指令,并显示出来

x86汇编_u命令1.png

  1. 输入 u 1000:00 后回车,可以将段地址为 1000,偏移地址为 0 的内存地址上的机器码翻译为汇编指令,并显示出来

x86汇编_u命令2.png


a 命令

  1. 输入 a 1000:00 后回车,可以向段地址为 1000,偏移地址为 0 的内存地址上输入汇编指令,输入完成后,继续回车结束

x86汇编_a命令1.png


t 命令

  1. 输入 t 后回车,即可从 CS:IP 所指向的地址取出一条指令单步执行(需要提前指定 CS 和 IP 的值

x86汇编_t命令1.png


p 命令

  1. 对于存在 loop 循环的程序,先单步执行到 loop 指令,使用 p 命令可以直接执行到 CX = 0 跳出循环

x86汇编_p命令1.png


g 命令

  1. 该命令后面可以跟地址和断点,运行到内存指定位置的代码,也可以用 g 命令来跳过 loop 循环

x86汇编_g命令1.png


debug 中的标志寄存器

在 DEBUG 中,标志寄存器是按照有意义的各个标志位单独表示的

x86汇编_debug中的标志寄存器1.png

  • 在 DEBUG 中对已知标志位的表示:
标志值为 1 的标记值为 0 的标记
OFOVNV
DFDNUP
SFNGPL
ZFZRNZ
PFPEPO
CFCYNC