第八章 数据处理的两个基本问题
1)处理的数据栈什么地方?
2)要处理的数据有多长?
定义一个描述符号:reg表示寄存器 sreg表示段寄存器
reg:ax , bx, cx, dx, ah, al, bh, bl, ch, cl, dh, dl, sp, bp, si, di;
sreg: ds, ss, cs, es
8.1 bx, si, di 和bp
1)只有这4个寄存器可以用在 [...]进行内存单元地址。
mov ax, [bp]
mov ax, [bp + si]
其他通用寄存器不可取地址
2)在[...]中它们部分可以两两组合,或者再加上idata
bx 和 si
bx 和 di
bp 和 di
bp 和 si
si+di bx + bp 都是错误的
3)在[...]中使用BP 而没有给出段地址,默认段地址在ss中
mov ax, [bp] (ax) = ((ss)*16 + (bp))
mov ax, [bp + idata] (ax) = ((ss)*16 + (bp) + (idata))
mov ax, [bp + si] (ax) = ((ss)*16 + (bp) + (si))
mov ax, [bp + si + idata] (ax) = ((ss)*16 + (bp) + (si) + idata)
8.2 机器指令处理的数据在什么地方
处理大致可分为3类 : 读取, 写入, 运算
8.3 汇编语言中数据位置的表达
1) 立即数 idata 直接包含在机器指令中的数据(执行前中cpu的指令缓冲器中
例如
mov ax, 1
add bx, 2000h
or bx, 00010000b
mov al, 'a'
2) 寄存器
指令要处理的数据中寄存器中,在汇编指令中给出相应的寄存器名
例 mov ax, bx
mov ds, ax
push bx
...
3) 段地址(SA)和偏移地址(EA)
指令要处理段数据中内存中,用[...]给出
mov ax, [0]
mov ax, [di]
mov ax, [bx + 8]
mov ax, [bx + si + 8]
段地址在DS中
mov ax, [bp]
mov ax, [bp + 8]
mov ax, [bp + si]
mov ax, [bp + si + 8]
段地址在ss中
也可以显示给出段地址
mov ax, ds:[bp]
mov ax, es:[bx]
mov ax, ss:[bx+ si]
mov ax, cs:[bx + si + 8]
8.4 寻址方式
见数164页
8.5 指令要处理段数据有多长
8086支持byte 和word两种尺寸段数据。
1)通过寄存器名制定要处理段数据的尺寸。
mov ax, 1
mov bx, ds:[0]
mov ds:[0], ax
int ax
字操作
mov al, 1
mov al, bl
mov al, ds:[0]
mov ds:[0], al
字节操作
2)在没有寄存器名字存在的情况下用符号 X ptr 指明内存单元的长度例如 word byte
字单元操作
mov word ptr ds:[0], 1
mov word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx], 2
字节单元操作
mov byte ptr ds:[0], 1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx], 2
3) 其他方法
有些指令默认类访问是字单元还是字节单元,例如push [1000H] 默认就是字操作
8.6 寻址方式的综合应用
8086 提供的[bx+si+idata]的寻址方式为结构化数据的处理提供类方便。是的我们可以在编程的时候,从结构化的角度取看待所要处理的数据。
一般来说用bx定义结构体 用idata定义结构体的某一数据项,在用si取定位数据项中的每个元素。
[bx].idata
[bx].idata[si]
8.7 div指令
div是除法指令
1)除数:有8位和16位两种,在一个reg或者内存单元中
2)被除数: 默认放在AX 或 DX中, 如果除数位8位, 被除数则为16位,放在AX中
如果除数为16位,则被除数为32为,在DX和AX中存放,DX中存放高16位,AX存放低16位
3)结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;
如果除数位16位,则AX存储除法操作的商,DX存储除法操作的余数
格式如下
div reg
div 内存单元
div byte ptr ds:[0]
(al) = (ax) / ((ds) * 16 + 0) 的商
(ah) = (ax) / ((ds) * 16 + 0)的余数
div word ptr es:[0]
(ax) = [(dx) * 10000H + (ax)] / ((es)* 16 + 0)的商
(dx) = [(dx) * 10000H + (ax)] / ((es) * 16 + 0)的余数
编程利用除法指令计算100001/100
100001 = 0x186a1h
;div program
assume cs:code
code segment
start: mov dx, 1
mov ax, 86a1h
mov bx, 100
div bx
mov ax, 4c00h
int 21h
code ends
end start
执行结果
计算1001/100
;div program
assume cs:code
code segment
start: mov ax, 3E9H
mov bl, 100
div bl
mov ax, 4c00h
int 21h
code ends
end start
计算结果
8.8 伪指令dd
dd dword(double word) 双字型 4个字节
data segment
dd 1
data ends
问题8.1 用div计算data段中第一个数据初一第二个数据后段结果,商存在第三个数据段存储单元中
;div program
assume cs:code, ds:data
data segment
dd 100001 ;4byte
dw 100
dw 0
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, ds:[0]
mov dx, ds:[2]
mov bx, ds:[4]
div bx ; equal to div word ptr ds:[4]
mov ds:[6], ax
mov ax, 4c00h
int 21h
code ends
end start
运行结果
8.9 dup
汇编语言的一个操作符由编译器识别处理。 用来进行数据重复
比如 db 3 dup(0)
定义来3个字节,它们的值都是0 相当于 db 0,0,0
db 3 dup (0, 1, 2) 相当于定义来9个字节 db 0,1,2,0,1,2,0,1,2
db 3 dup('abc', 'ABC') 相当于 'abcABCabcABCabcABC'
dup的常用格式如下
db 重复次数 dup (重复的字节型数据)
dw 重复次数 dup (重复的字型数据)
dd 重复次数 dup (重复的双字节数据)
例如要定一个一个200字节的空间
stack segment
db 200 dup (0)
stack ends
实验7 寻址方式中结构化数据访问中的应用
计雇员年收入平均值并将数据放置于table段中
assume cs:code, ds:data, ss:stack
data segment
;offset A = 0000H
db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983'
db '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992'
db '1993', '1994', '1995'
; the above data present the 21 x4 years
;offset A + 21x4(54H)
dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000
; the above data present the 21 dword for the income
;offset A + (54H) + (54H) = A8H
dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1441, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
; the above data present the number of employeer for the 21years
;offset A + A8H + 2A = D2
data ends
table segment
db 21 dup ('year summ ne ?? ') ; 21 x 16byte characters
table ends
stack segment
db 16 dup (0)
stack ends
code segment
start: mov ax, data
mov ds, ax ; set ds to data
mov ax, table
mov es, ax ; set es to table
mov ax, stack
mov ss, ax
mov sp, 10h ; set ss and sp
mov bp, 0 ; ofset for table
mov bx, 0 ; offset for data
mov di, 0 ; the word offset of data segment
mov cx, 21
s: push cx ; main loop for 21times
mov si, 0
mov cx, 4 ; sub loop s0 to mov the year data
s0: mov al, 0[bx][si]
mov es: 0[bp][si], al
inc si
loop s0
mov si, 0
mov cx, 2
s1: mov ax, 54H[bx][si] ; sub loop to move the incoming data
mov es: 5H[bp][si], ax
add si, 2
loop s1
mov ax, 0a8h[di] ; mov the number of employeer
mov es: 0ah[bp], ax
push bx ; calc the average incoming
mov ax, es: 5H[bp]
mov dx, es: 7H[bp]
mov bx, es: 0ah[bp]
div bx
mov es: 0dh[bp], ax
pop bx
add bx, 4
add di, 2
add bp, 10h
pop cx
loop s
mov ax, 4c00h
int 21h
code ends
end start
运行结果