汇编语言(王爽)-数据处理的两个基本问题


  1. 处理的数据在什么地方?

  2. 要处理的数据有多长?

这两个问题,在机器指令中必须给以明确或隐含的说明,否则计算机无法进行工作

定义描述性符号:regsreg

reg表示一个寄存器,包括:axbxcxdxahalbhblchcldhdlspbpsidi

sreg表示一个段寄存器,包括:dssscses


bx、si、di和bp

  1. 8086CPU中,只用这4个寄存器可以用在[ ]中来进行内存单元的寻址

  2. [ ]中,这4个寄存器可以单个出现,或只以4种组合出现

    1. bxsi

    2. bxdi

    3. bpsi

    4. bpdi

  3. 只要在[ ]中使用寄存器bp,而指令中没有显性给出段地址,段地址就默认在ss


机器指令处理的数据在什么地方

绝大部分机器指令都是进行数据处理的指令,处理大致分为3类:读取、写入、运算

指令在执行前,所要处理的数据可以在3个地方:CPU内部、内存、端口


汇编语言中数据位置的表达

  1. 立即数(idata)

    对于直接包含在机器指令中的数据(执行前在CPU的指令缓冲器)称为立即数,在汇编指令中直接给出

  2. 寄存器

    指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名

  3. 段地址(SA)和偏移地址(EA)

    指令要处理的数据在内存中,在汇编指令中可用 [ ]的格式给出EASA在某个段寄存器中

    存放段地址的寄存器默认在dsss中,也可以显性给出


寻址方式

当数据存放在内存中时,可以使用多种方式给定内存单元的偏移地址,这种定位内存单元的方法一般称为寻址方式

1.png


指令要处理的数据有多长

8086CPU的指令,可以处理两种尺寸的数据,byteword

在机器指令中要指明,指令进行的是字操作还是字节操作

  1. 通过寄存器指明要处理的数据的尺寸

    使用ax等寄存器时,表示进行的是字操作

  2. 在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以是wordbyte

    1. word ptr指明了指令访问的内存单元是一个字单元

      mov word ptr ds:[0],1

      inc word ptr [bx]

      inc word ptr ds:[0]

      add word ptr [bx],2

    2. byte ptr指明了指令访问的内存单元是一个字节单元

      mov byte ptr ds:[0],1

      inc byte ptr [bx]

      inc byte ptr ds:[0]

      add byte ptr [bx],2

      在没有寄存器参与的内存单元访问指令中,用word ptrbyte ptr显性的指明所要访问的内存单元的长度是很必要的。否则,CPU无法得知所要访问的单元是字单元,还是字节单元

  3. 其他方法

    有些指令默认了访问的是字单元还是字节单元。如:push指令只进行字操作


寻址方式的综合应用

记录更改

原纪录:

1
2
3
4
5
6
7
8
9
公司名称:DEC

总裁姓名:Ken Olsen

排名:137

收入:40

著名产品:PDP

2.png

新记录:

1
2
3
4
5
6
7
8
9
公司名称:DEC

总裁姓名:Ken Olsen

排名:38

收入:110

著名产品:VAX

汇编程序

1
2
3
4
5
6
7
8
9
10
11
12
13
mov ax,seg
mov ds,ax
mov bx,60h

mov word ptr [bx+0ch],38
add word ptr [bx+0eh],70

mov si,0
mov byte ptr [bx+10h+si],'V'
inc si
mov byte ptr [bx+10h+si],'A'
inc si
mov byte ptr [bx+10h+si],'X'

bx定位整个结构体,用idata定位结构体中的某一个数据项,用si定位数组项中的每个元素。为此,汇编语言提供了更为贴切的书写方式:[bx].idata[bx].idata[si]


div指令

div是除法指令

  1. 除数:有8位和16位两种,在一个reg或内存单元中

  2. 被除数:默认放在axdxax

    若除数为8位,被除数则为16位,默认在ax中存放

    若除数为16位,被除数则为32位,则在dxax中存放,dx存放高16位,ax存放低16位

  3. 结果:

    若除数为8位,则al存储除法操作的商,ah存储除法操作的余数

    若除数为16位,则ax存储除法操作的商,dx存储除法操作的余数

格式:div regdiv 内存单元

例:

  1. 1
    2
    3
    4
    div byte ptr ds:[0]

    (al)=(ax)/((ds)*16+0)的商
    (ah)=(ax)/((ds)*16+0)的余数

    除数存储在ds:[0]中,除数8位,则被除数16位,存储在ax中;al存储除法操作的商,ah存储除法操作的余数

  2. 1
    2
    3
    4
    div word ptr es:[0]

    (ax)=[(dx)*10000H+(ax)]/((es)*16+0)的商
    (dx)=[(dx)*10000H+(ax)]/((es)*16+0)的余数

    除数存储在es:[0]中,除数16位,被除数32位,dx存放被除数高16位,ax存放被除数低16位;ax存储除法操作的商,dx存储除法操作的余数

  3. 1
    2
    3
    4
    div byte ptr [bx+si+8]

    (al)=(ax)/((ds)*16+(bx)+(si)+8)的商
    (ah)=(ax)/((ds)*16+(bx)+(si)+8)的余数
  4. 1
    2
    3
    4
    div word ptr [bx+si+8]

    (ax)=[(dx)*10000H+(ax)]/((ds)*16+(bx)+(si)+8)的商
    (dx)=[(dx)*10000H+(ax)]/((ds)*16+(bx)+(si)+8)的余数

编程实现计算100001/100

分析:

  1. 被除数100001大于65535(多于16位),不能使用ax寄存器存放,使用dxax一起存放

  2. 除数100小于255,可以使用一个8位寄存器存放。但因被除数是32位的,除数应为16位,所以应使用一个16位寄存器来存放除数100

1
2
3
4
mov dx,1		;对dx赋值被除数高16位
mov ax,86A1H ;对ax赋值被除数低16位 (dx)*10000H+(ax)=100001
mov bx,100 ;赋值除数到bx寄存器中
div bx

伪指令dd

db用来定义字节型数据

dw用来定义字型数据

dd用来定义dword(double word双字)型数据

编程实现,第一个数据除以第二个数据,结果存在第三个数据的存储单元中

1
2
3
4
5
data segment
dd 100001
dw 100
dw 0
data ends

分析:dd定义第一个数据,为双字型数据,32位,将第一个数据存储在dxax

1
2
3
4
5
6
mov ax,data
mov ds,ax
mov ax,ds:[0] ;被除数低16位存储在ax中
mov dx,ds:[2] ;被除数高16位存储在dx中
div word ptr ds:[4]
mov ds:[6],ax ;除法完成后,默认商存储在ax中,将商转存至第三个数据存储空间中

dup

由编译器识别处理的操作符

dbdwdd等数据定义伪指令配合使用,用来进行数据的重复

格式:

  1. db 重复的次数 dup (重复的字节型数据)

  2. dw 重复的次数 dup (重复的字型数据)

  3. dd 重复的次数 dup (重复的双字型数据)

例:

  1. db 3 dup (0)

    定义3个字节,值为0,相当于db 0,0,0

  2. db 3 dup (0,1,2)

    定义9个字节,值为0、1、2、0、1、2、0、1、2,相当于db 0,1,2,0,1,2,0,1,2

  3. db 3 dup ('abc','ABC')

    定义了18个字节,值是abcABCabcABCabcABC,相当于db 'abcABCabcABCabcABC'

当定义大容量的数据段或者栈段时,使用dup可以使程序简短

定义一个200个字节的栈段

1
2
3
stack segment
db 200 dup (0)
stack ends
---------------The End---------------
0%