汇编学习(持续更新中...)
20190226
寄存器
AX,BX,CX,DX寄存器与其他寄存器的区别在于:
- 它们是两个字节
- 可以分为高位和低位AH,AL .etc.
- 数据与寄存器之间要保持一致性 8位给8位,16位给16位;
- 8位寄存器保存8位数据,运算结果大于8位的保存到其他地方去了(后面会讲到),并不会保存到高位;寄存器做运算时是相互独立的,AL和AH之间不会相互影响。
地址寄存器
- 代码段寄存器CS:存放当前执行的程序的段地址;
- 数据段寄存器DS:存放当前执行的程序所用操作数的段地址;
- 堆栈段寄存器SS:存放当前执行的程序所用堆栈的段地址;
- 附加段寄存器ES:存放当前执行程序中一个辅助数据段的段地址。
偏移地址寄存器
- bx
- bp
- si
- di
- cs:用来存放诸如dw定义的字型数据;
地址加法器
【问】8086/8088的地址加法器有何作用?试举例加以具体阐述。
【答】地址加法器用于产生20位的物理地址。由于8086/8088有20根地址线,但内部寄存器却只有16位,而16位寄存器不能直接为20根地址线提供20位寻址信息。为了解决这一矛盾,8086/8088 CPU采用了将地址空间分段的方法.即将1MB的地址空间分为若干个64KB的段,然后用20位的段起始地址(即段基地址或简称段基址)加上16位的段内偏移地址(简称偏移)来访问物理存储器。
比如,CPU要形成某个指令代码的物理地址,就要将IP的值与代码段寄存器CS左移4位后的内容相加。假设CS=2000H,IP=0414H,此时指令的物理地址为20414H。
- 物理地址的计算
物理地址=段地址×10H + 偏移地址(0~FFFFH)
073F为段地址,后边的两个字节为偏移地址。
上图CPU将CS&IP所指向的内容当作指令来执行
上图e指令可以用来修改内存中的值
DOSBOX使用手册
debug模式下的一些命令:
-a 输入汇编指令;
-d 查看指定物理内存的值(-d 段地址:偏移地址)
-r 读取各个寄存器的值;
-r ds+回车即可修改ds寄存器中的值;
-t 逐行执行
-u 指令将机器码翻译成汇编语言
-e 用来修改内存的值(机器码)
-jmp ax 把ax中的值存入IP
通过指令中的AX/AL/AH确定是字节型数据or字型数据
- 字型数据需要两个连续的字节存放,高地址存放高位字节,低地址存放低位字节;
栈
- 入栈(push):将16位寄存器或者内存中的字型数据放入栈顶标记的上面;修改栈顶标记;
- 出栈(pop):将栈顶标记所标识的字型数据放入16位寄存器或内存中;修改栈顶标记。
- 栈顶标记:在8086CPU中,在任意时刻将段地址寄存器SS和偏移地址寄存器SP所组合出来的内存地址当作栈顶标记。
- PUSH&POP执行指令过程SS:SP(段地址:偏移地址)
- 关于push操作是sp=sp-2的理解:设置栈的大小就是指定sp的值,每push一次栈的剩余空间就会减小,只有sp不断减小直至0(ss),才可以控制栈的大小。注意一定要避免栈的越界问题。
- SP寄存器的变化范围:0~FFFFH,32768个字型数据(需要将SS设置为0)
- call 16位reg:执行过程——
push IP;jmp 16位reg
-
ret和call配合使用,可将数据从栈中取回,执行过程——
pop IP
汇编语言
构成
设置不同的代码段而不是全部都塞在代码段中的好处1:程序看起来简洁明了;好处2:节省IP的值。
需要注意的是:数据段和代码段设置了dw之后需要在代码段中引用CPU才可以使用之。
- 栈段
- 代码段
- 数据段
组成
- 汇编指令
- 伪指令
- 符号体系
DOSBOX下程序的跟踪
- -debug+程序名
- cx寄存器存放程序的长度
- 在执行-loop(汇编)指令时,-p(DOSBOX调试)指令可以直接跳转到loop指令的下一条指令,省去了一步步-t指令操作;
- g(DOSBOX调试)指令:
- 汇编中loop指令的使用:需要注意的是,CX初始值为0会发生越界的现象,CX中存放循环次数。
- int 21H:是DOS的中断调用
比如 MOV AH 4CH INT 21H 是返回DOS系统的 通过给AH寄存器赋值4CH,然后调用INT
21H指令,计算机就会根据AH寄存器中的值执行相应的操作,其中4CH是返回DOS系统,还可给AH寄存器赋其他值,所对于的操作这里也有
-
Inc bx指令自加,省内存;
上图为int指令相关 -
start指令&-end start指令可以用来确定编译指令的起始&终止位置,成对出现;jmp也可决定起始执行位置;
-
PSP区:从ds[0]开始的256个字节,是程序用来和系统之间通信的
编译需要注意的规则
- 任何字母前都需要加0,比如,应该是
0B800H
而不是B800H
- *.asm文件中的10和直接在DOSBOX中的10是有区别的:源代码中的10会在dos编译时翻译为A,即按十六进制处理;
- 分号后加注释;