x86

DOS基础与汇编

x86

Posted by Bruce Lee on 2023-07-14

汇编开始的地方(至稚嫩的自己)

DOSBox上编程

MOUNT命令,挂载c盘,将源地址挂载出去
使用C:命令,切换目录
使用masm命令来编译asm文件,生成obj文件
使用link命令来链接obj文件,生成exe文件
源文件必须放在MASM文件目录下,减少冗余的文件目录

进入挂载masm后的c盘中,使用edit文本编辑器经行asm文件代码编写
(masm后面加入当前目录下的文件,可以省略扩展名,当源文件不在当前文件下
需要masm后加入完整的盘符加路径加文件名)
然后进行masm编译
(编译之后默认是生成在当前目录下的.obj文件)
然后进行link连接
(因为生成的目标文件是默认在当前目录下的,所以可以直接link+文件命,可以不需要加扩展名)
可以直接使用(直接运行exe文件)

可以使用debug模式,对exe文件进行单步跟踪 debug+可执行文件名.exe
(在源文件中,使用内存的数据,ds指向数据段,命令语句中,如[0006],[0006h],不代表是ds:[0006},(ds*16+6)H标识的地址,而是6h值,必须将偏移地址值mov给
bx寄存器,然后在命令语句中使用[bx]来表示偏移地址)(可以使用ds:[0006]

ax,bx,cx,dx的常用
ax经常在程序返回的时候使用,如在功能代码执行完之后,需要将cpu的执行权力返回给调用程序,需要
mov ax,4c00h(这个寄存器只能是ax,当我使用别的通用寄存器的时候,dos会崩溃)
int 21h
两行代码
bx经常在使用内存定位时,充当偏移地址的使用,[bx]
cx,在loop指令时,常用作循环的次数

ss:sp,作为栈段的时候,如果我们将ds指向同一个地方,然后将栈顶内容pop到数据区的时候,会发生不可描述的错误

p命令和t命令的区别,t只是表达下一条指令,cpu只会不顾一切的执行下一条指令,而p指令,是proceed的时候,意味着持续执行,但是是从上一个断点到下一个断点,程序最后
的命令是int 21h p命令执行这个指令后,就会返回程序,而t命令则不会

p命令在一般语句中,功能类似与t命令,在loop指令中,可以直接运行完loop指令

内存偏移地址,不能用【ax】,还只能用【bx】

一个好习惯就是在访问内存单元的时候,一定在前面加上段前缀

在描述内存单元的时候,可以用任意一个段寄存器来描述,但是需要在前面加上段前缀,如果不加上段前缀,就是默认是ds段寄存器作为段地址
常用es段,extro来作为另外一个指向段地址

mov指令中,段寄存与段寄存器之间不能直接传送

mov,add指令中,长度是依据于mov本事的大小和操作数的大小

8086cpu中,不能在源程序中,写下直接修改ip寄存器的指令
同时,在实现跳转指令的时候,label这个标签是不可用的

关于ss空间的分配引发的思考,对于dw 0,0
实际分配空间最少时010h个

1.大小写转换问题-实验 将and,or指令,讲述编程哲学,我们都是在ascll层面经行编程,数值6,字符6

2.data segment 的定义是,dd dw db 多个数时,能不能使用dup

3。寻址时,我们和c语言对比

4.寄存器常用组合集合+div指令

nop指令(扩充知识)

转移指令的机器码分析(相对地址,不是绝对地址)

转移指令的短,近转移,loop循环,jcxz转移,都是相对转移,1.为什么采用相对转移,2绝对转移的程序的机器码,如果要移植,都必须将源程序移植,然后重新编译,连接吗
1.增加可移植性,浮动装配2.有短,近转移,提高利用率。3补码表示,来标识上下方向的跳转,其上下距离最大为2^7,2^15
jmp直接转移内存单元的时候,jmp + 内存单元地址,分为字空间,和双字空间,内存空间的值,是偏移,段地址的值

最好不要移送jmp指令的机器码,除非是绝对地址的jmp指令

关于立即数,如果最高位是字母,在前面一定要加上一个0

lab9中,如何将写入B8000内存中的数据,显示在屏幕上,调用int 10h 中断

所谓除法溢出,指的是,在被除数的存储中,涉及到dx存高位字节,ax存低位字节,所得结果中,商存ax,余数存dx-16位除法
8位除法的结果是ah存余数,al存商。存在一个问题,就是商,可能会超过存储的空间大小

中断向量表的内存地址,有思考的趣味

所有汇编指令的微型操作整理

补充

首先,使用mount 指令,这是一个挂载指令,我们可以这样来简单的理解。

这个mount 指令呀,就相当于c语言中#define ,我们使用这个来将复杂的,不易理解的东西,换个名称来表达,利于后续的开发。

比如在我的电脑上,我是这样挂载的(这是挂载指令,当然用挂载来表达啦)

mount C G:\develop\DOS\root\DOSBox-0.74-3\MASM

这是在DOS单任务操作系统命令行中打出的指令,我的编译器masm 是放在G盘中,develop开发目录,DOS操作系统目录,root根目录,DOSBox目录下的MASM目录,如果我在后续的操作中,反复在这个大串目录下和c盘或其他盘的目录进行操作,那么我将反复打出这些大臭长串,这样的后果就是不利于开发,效率底下。

那么这样讲你就可以理解mount 的作用了,它就是将C盘

C:\

作为这个一大臭长串的代表盘符+目录。

我们在命令行下,继续输入

C:

那么我们就可以把这个C盘作为这个一大臭长串的代表,我们相当于在这个大臭长串下进行一系列的操作。

最简单的寄存器(通用寄存器)

挂载完成之后,输入

C:(按下回车)

debug(按下回车)

然后我们就进入调试模式啦,输入r 命令,我们可以查看cpu 中寄存器的状态(就是寄存器中存储的值)

最简单的寄存器的名字叫做ax 寄存器,至于为什么叫做ax ,这是跟跟单词accumulator 有关,其全名叫做Accumulator Register ,我们管它叫作通用寄存器,x 后缀就是代表它是一个通用寄存器,8086cpu 中,一共有4个通用寄存器,加上刚刚说的ax 寄存器,还有bx 寄存器(Base Register),cx 寄存器(Count Register),dx 寄存器(Data Register),好啦,这就组成了这大名鼎鼎的通用寄存器ax,bx,cx,dx 。我们在记忆的时候可以这样想啦,依次是a,b,c,d,然后后缀加上x。一定要记住咯,x后缀表示是通用寄存器哦。

神奇的指令寄存器(CS:IP)

cpu 是怎么知道我们的代码存储在哪里的呢,我们写的汇编程序存储在内存中,可是内存这么大块,cpu 怎么知道我们要执行的程序有多大,占据的内存空间是多少?

先告诉你cpu 是个什么样子的东西:cpu 是一个智能的笨蛋。

当我们的程序存储在内存中时,我们使用cs 寄存器,ip 寄存器,来指向程序的第一个指令的地址,我们的cpu 就可以从cs 寄存器,ip 寄存器中得知,它下一条的指令在内存的哪里。

cs 寄存器的全名叫做code segment (代码段),顾名思义,它所指向的内存就是我们的代码,就是cpu 下一条指令的位置。

ip 寄存器的全名叫做instruction pointer (指令指针),en~,它的作用其实就是cs 寄存器的作用,嗯?不对呀,怎么这两个寄存器的作用重合了,其实没有重合,而是它俩配合起来,才能真正指向内存中的指令。我们接下来就需要先理解,在cpu 中,内存地址是怎么表示,存储的。

8086cpu的内存地址表示和段寄存器的知识

mov指令的内存大小真的是固定的吗

我们经常会在编写完源程序的时候,使用debug (调试)模式来查看cpu中各个寄存器的状态(就是寄存器中存储的值啦),使用u 命令,我们可以查看内存中存储的机器码所对应的汇编代码,u命令呀,就是unassemble的意思啦(反汇编),assemble就是汇编的意思啦。

输入

u cs:0000

我们可以看到我们的程序被masm编译器编译之后,变成机器码,然后再经过debug程序,将机器码变成汇编代码之后的样子,是不是看起来很绕,确实有点绕,说白了,u 命令就是将内存中存储的值解释为汇编代码,然后呈现给你。

到这里之后,我们在以往的编程过程中,经常看到mov 指令占据的内存大小,通常是3个字节,一些教科书中,也没有明确说明mov 指令是固定大小的,只是说,mov 指令占据3字节,add 指令占据2字节,我怕我误会了教科书的严谨性,所以我认为这句话是出现在特定的程序下的,但是读者可能会认为,不管什么程序环境下(必须在8086cpu和DOS系统下),mov 指令一定是3字节,add 指令一定是2字节。这是错误的,不信的话,你自己编程看看,写完程序后通过编译,连接程序,使用debug 模式,u 命令查看反汇编代码,源程序分别写入

mov 寄存器,内存地址

mov 内存地址,寄存器

mov 寄存器,立即数

mov 寄存器,寄存器

这些个指令模式,你实验后看看,各个指令占据的内存大小一定是3字节吗。同样的,可以试试add 指令。

7/14/2023 12:41:01 AM

mov指令的大小到底怎么算的?

其实,常说mov 指令大小是固定的,一般是指mov 指令的本身的大小,就好比,一辆轿车的重量(假如全世界的轿车出厂都是2吨),站在工业生产的角度,那么我们就说,轿车的重量是固定的,就是两吨。如果在日常生活中,我们谈及这轿车的重量的时候,还会说它的重量是固定的吗,当然不会啦,我们就会说,轿车的自身重量是固定的,但是车上还有人和物品,车的重量依据具体的人和物,加上本身的重量,才能确定最终真实的重量。所以啦,mov 指令的大小,要依据自身和具体的操作数来确定大小,一般来说,操作数越大,占据的字节数越多,寻址方式越简洁,占据的字节数越少(比如直接寻址,寄存器寻址,反之,如内存寻址)。

7/14/2023 12:41:23 AM


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. All the images used in the blog are my original works or AI works, if you want to take it,don't hesitate. Thank you !