0%

第一章_汇编语言基础

数据表示

BCD码

视频讲解:BCD码讲解

BCD码在加法运算超过10的时候需要矫正,在原先运算基础上加6

举例

有符号数的表示方法

原码:

符号位1表示负数,0表示正数

反码

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

补码

正数的补码就是其本身

负数的补码是在反码的基础上+1

取反加1得到负数的绝对值,正数的相反数


举例:


8086寄存器

下面这张图要能背下来

通用寄存器

数据寄存器(保存操作数或运算结果)

  1. 累加器AX
  2. 基址寄存器BX
  3. 计数器CX
  4. 数据寄存器DX

指针寄存器(存放某个存储单元的偏移地址)

  1. SP堆栈指针寄存器(存放堆栈段中栈顶的偏移地址)
  2. BP基址指针寄存器(存放堆栈段中某一存储单元的偏移地址)

变址寄存器(存放某个存储单元的偏移地址)

  1. SI源地址变址指针寄存器
  2. DI目标地址变址寄存器

控制寄存器

IP指令指针寄存器

FLAGS标志寄存器

  1. AF(Auxiliary carry Flag)辅助进位标志
  2. CF:(Carry Flag)进位标志
  3. OF(Overflow Flag)溢出标志
  4. PF:(Parity Flag)奇偶标志
  5. SF(Sign Flag)符号标志
  6. ZF(Zero Flag)零标志

段寄存器

段寄存器,不是用于提供偏移地址的寄存器,而是用于定义段的起始地址

CS代码段段寄存器

DS数据段段寄存器

ES附加段段寄存器

SS堆栈段段寄存器

8086的存储器组织

存储单元的地址

每一个字节单元都有一个与之对应的单元地址。

对于多字节单元(字,双字,4字等),其地址同样是采用最低位字节地址来表示的。

存储单元内容

如果X是地址,(X)表示从X地址从取内容

如果X是地址的地址,取内容用((X))

举个例子

存储器地址的分段

分段基本规则:从0地址开始,每16个字节为一小段。

段地址和偏移地址

段地址:表示一个段的开始

偏移地址:在段内相对于段起始地址的偏移值。如当偏移量为‘0’时,就在这个段的起始单元,当偏移量为0FFFFH时,就是这个段(最大)最末一个字节单元。

物理地址和逻辑地址的关系(重点)

常见的组合形式:

段地址:偏移地址(IP)

其中段地址保存的是起始段的首地址,偏移地址(IP)里面保存的是相对于段地址的数据偏移地址空间

段地址有:CS, DS, ES, SS

物理地址=段地址×10H+偏移地址

举个例子

段地址与段寄存器

段分配

举例1

举例2

隐含段和偏移寄存器

8086的寻址方式

寻址方式

基本格式

操作数字段可以为0个、一个、二个或三个。对应的称为零地址指令、一地址指令、二地址指令或三地址指令

典型二地址指令,源操作数和目标操作数

执行的操作: (DST)←(SRC)

数据寻址方式

从最本质的出发看,MOV指令就3种用法

1. 直接将数据保存到目标寄存器中

2. 直接将源寄存器中保存的内容转移保存到目标寄存器中

3. 根据偏移地址计算物理地址再放入寄存器中,只要源操作数带[],就是这种方法

综上,MOV之后目标寄存器里保存的是内容而不是地址!

比较重要的点:

1. 8086CPU中是不支持将数据直接保存到段寄存器的,需要先保存到通用寄存器(AX, BX, CX, DX), 再保存到段寄存器(CS,DS, ES, SS)

2. 直接MOV立即数进内存的时候要在内存前加前缀,来指明立即数的位数

3. MOV不能修改CS和IP这两个寄存器

立即寻址方式:

操作数直接存放在指令中

1
2
3
MOV  AL, 5
MOV AX, 3064H
MOV EBX,12345678H

其中AL表示的意思是数据寄存器中累加器的低八位

EBX表示比8086更高级寄存器中拓展的累加器,8086是16位,拓展后是32位

注意:源 和 目标 的字长(位数)要一致。

错误指令事例

  1. 位置放反

    1
    MOV    2000H,AX     源操作数和目标操作数位置反了
  2. 长度不等

    1
    MOV    DL,300H      DL是低8位,两个字节,300H,一个数字由4个字节组成,所以说是16进制,3个数字说明是3个字节,长度不等
  3. 超过范围

1
MOV    AH,257       AH是累加器中高八位,最大可以放大数字在不考虑符号情况下是255(2^8 = 256)

执行指令举例

【例】:执行指令 MOV AX,5678H

寄存器寻址方式

1
2
3
MOV  AL, CL
MOV CX, DX
MOV EAX,EBX

注意: ● SRC 和 DST 的字长(位数)要一致。 ● DST不能为CS(代码段寄存器)

错误举例

  1. CS不能修改

    1
    MOV    CS,AX  		CS不能作为目标操作数
  2. 长度不等

1
2
MOV    DL,BX			长度不等
MOV SI,EAX 长度不等

直接寻址方式

默认情况: 物理地址=DS×10H+EA

举例

例如,若指令为  MOV  AX,ES:[VALUE]
则对应该SRC的物理地址为 ES×10H+EA

例题

【例】: 指令 MOV AX, [ 2000H ] ,其中DS=3000H。(32000H) = 3050,该指令执行完后,AX的值。

一种比较容易犯的经典错误

寄存器间接寻址方式:

计算物理地址公式:

除了BP寄存器默认段地址是SS,其他寄存器默认的段地址都是DS

如果指令中指定的寄存器是BX,没有指出段跨越前缀,则操作数默认放在数据段中,所以用DS寄存器的内容作为段地址,即操作数的物理地址(PA)为: PA=DS×10H十BX或SI或DI

如果指令指定BP寄存器,则操作数默认放在堆栈段中,段地址在SS中,即操作数的物理地址为: PA=SS×10H十BP

与直接寻址方式一样,寄存器间接寻址指令也可指定段跨越前缀来取得其它段中的数据。对于指定段跨越前缀(如使用ES),则操作数的物理地址为: PA=ES×10H十BX或SI或DI

举例:

【例】: 分析指令① MOV AX,ES:[BX] ② MOV AX,[BX]
执行后AX的值各是多少? 已知 DS=2000H, ES=4000H,BX=0300H,(40300H)=0DE10H ,(20300H)=27ABH 【解】: ① (确定是ES)源操作数对应的物理地址 =4000H×10H十0300H = 40300H 则执行指令后, AX=0DE10H。 ② (默认是DS)源操作数对应的物理地址 =2000H×10H十0300H = 20300H 则执行指令后, AX=27ABH。

【例】: ADD AX,[BP]
指令执行前: AX=50A0H,BP=0025H, SS=3000H,(30025H)=471AH。 源操作数对应的物理地址 =SS× 10H 十 BP =3000H×10H十0025H =30025H 执行指令:(注意,是ADD,要将之前计算出的物理地址内存储的数取出与目标地址原来保存的数相加) (30025H)+ AX
=471AH+50A0H =97BAH 则指令执行完后,AX=97BAH。

寄存器相对寻址方式

注意:对于8位位移量,计算时要扩展到16位(带符号)。即:对于00H---7FH的数,扩展成16位带符号数时,高8位直接填零,为:0000H---007FH;若为8XH以上的数,扩展后为0FF8XH。

举例:

【例】 分析指令 MOV AX,DISP[DI] (或写成MOV AX,[DI+DISP]) 执行后,AX的值。 已知 DS=4000H,DI=2000H,DISP=1000H;设指令执行前: AX=7C69H,(43000H)=55H,(43001H)=66H。

计算有效地址EA: EA=2000H+1000H=3000H 对应物理地址=DS×10H+EA =40000H+3000H=43000H。 指令执行后: AX=6655H,(43000H)=55H,(43001H)=66H, DS=4000H,DI=2000H。

基址变址寻址方式

基址2个:BP和BX

其中BP指针寄存器默认对应SS段寄存器,BX指针寄存器默认对应BS段寄存器

变址2个:SI和DI

      EA=(RB)+(RI)

RB为基址寄存器,RI为变址寄存器.

【例】分析指令MOV DX,[BP+DI] ( MOV DX,[BP][DI])指令执行结果。 设SS=3000H,DS=2000H,BP=2000H,DI=0500H;指令执行前:DX=1234H,(32500H)=78H,(32501H)=56H

【解】:源操作数有效地址: EA=BP+DI=2000H+0500H=2500H; 源操作数的物理地址 PA=SS×10H+EA=30000H+2500H=32500H。 指令执行后: DX=5678H

相对基址变址寻址方式

物理地址表示:若无段前缀,使用BX时,默认使用段寄存器为DS,使用BP时,默认使用的段寄存器为SS。

程序存储器寻址方式

JMP指令

jmp 是无条件转移指令,

无条件转移指令可转到内存中任何程序段,

转移地址可在指令中给出,也可以在寄存器中给出,或在储存器中指出。

它可以只修改 IP ,也可以同时修改 CSIP

只修改IP的称为段内转移jmp ax 相当于 mov ax,ip

同时修改 cs:ip 的叫 段间转移jmp 1000:0

jmp 指令要给出两种信息:

1. 转移的目的地址 2. 转移的距离(段间转移、段内转移、段内近转移)

转移的目的地址在指令中的jmp指令:

段内转移,近转移

语法: jmp short 标号(转到标号处执行指令)

这种格式的 jmp 指令实现的是段内短转移

它对 IP 的修改范围为 -128~127

short 符号表示指令进行的是短转移

标号 指明了指令要转移的目的地

比如:

1
2
3
4
5
6
7
8
9
10
assume cs:codesg

codesg segment

start:mov ax,0
jmp short s
add ax,1
s:inc ax
codesg ends
end start

程序执行后,ax 中的值为 1

因为执行 jmp short s 后,越过了 add ax,1

IP 指向了 标号 s 处的 inc ax

也就是说,程序只进行了一次 ax1 操作

此种转移方式并没有转移的目的地址,而是相对于当前 IP 的转移位移

另外,近转移ip修改范围: -32768~32767

段间转移,远转移

语法: jmp far ptr 标号

这种实现的是 段间转移 ,又称为远转移

(CS)=标号所在段的段地址(IP)=标号在段中的偏移地址

far ptr 指明了指令用标号的段地址和偏移地址修改 CS 和 IP

上面只是解释jmp过程中cpu执行了什么,实际写程序直到jmp就是往设置的标号跳就行

比如:

1
2
3
4
5
6
7
8
9
10
11
12
assume cs:codesg

codesg segment

start:mov ax,0
mov bx,0
jmp far ptr s
db 256 dup (0)
s:add ax,1
inc ax
codesg ends
end start

转移地址在寄存器中的jmp指令

指令格式: jmp 16 位 reg

功能: (IP)=(16 位 reg)

比如:

1
2
3
指令执行前: ax=1000H ,CS=2000H ,IP=0003H
jmp ax
指令执行后: ax=1000H ,CS=2000H ,IP=1000H

jmp ax ,相当于: mov IP,ax ### 转移地址在内存中的jmp指令:

转移地址在内存中的jmp指令有两种格式

(1) jmp word ptr 内存单元地址(段内转移)

功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址

内存单元地址执行后, (IP)=0123H可用寻址方式的任一格式给出。

比如:

1
2
3
4
5
mov ax,0123H

mov ds:[0],ax ;将寄存器 AX 中的值移动到数据段(DS)中偏移量为 0 的位置处。

jmp word ptr ds:[0]

执行后, (IP)=0123H

又比如:

1
2
3
4
5
mov ax,0123H

mov [bx],ax

jmp word ptr [bx]

执行后, (IP)=0123H

(2) jmp dword ptr 内存单元地址(段间转移)

功能:从内存单元地址处开始存放着两个字,

高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址

1
2
(CS) = (内存单元地址+2)
(IP) = (内存单元地址)

内存单元地址可用寻址方式的任一格式给出

比如:

1
2
3
4
5
6
7
mov ax,0123H

mov ds:[0],ax

mov word ptr ds:[2],0

jmp dword ptr ds:[0]

执行后, (CS)=0 ,(IP)=0123H ,CS:IP 指向 0000:0123

再比如:

1
2
3
4
5
6
7
mov ax,0123H

mov [bx],ax

mov word ptr [bx+2],0

jmp dword ptr [bx]

执行后, (CS)=0 ,(IP)=0123H ,CS:IP 指向 0000:0123

小结:

jmp short 标号 功能为:段内短转移

(IP)=(IP)+8位位移

  1. 8位位移 = 标号处的地址 - jmp指令后的第一个字节地址
  2. short指明的此处是8位位移
  3. 8位位移的范围为-128-127,用补码表示
  4. 8位位移是编译程序时在编译时算出的

jmp near ptr 标号 功能为:段内近转移

(IP)=(IP)+16位位移

  1. 16位位移 = 标号处的地址 - jmp指令后的第一个字节地址
  2. short指明的此处是8位位移
  3. 16位位移的范围为-32768-32767,用补码表示
  4. 16位位移是编译程序时在编译时算出的