reg 的集合包括:
ax, bx, cx, dx, ah, al, bh, bl, ch, cl, dh, dl, sp, bp, si, di;sreg 的集合包括
ds, cs, ss, es8086CPU 中,只有 4 个寄存器可以用 “ [...] ” 来进行内存单元寻址。
bx, si, di, bp在 “ [...] ” 中,这4个寄存器可以单个出现, 或只能以 4中组合出现
(1)bx 和 si
(2)bx 和 di
(3)bp 和 si
(4)bp 和 di在 “ [...] ” 中使用 寄存器 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 )
指令执行前,所有处理的数据可以在 3 个地方: CPU内部, 内存, 端口。
汇编语言中数据位置的表达
(1)立即数 idata
直接包含在机器指令中的数据(执行前在 CPU的指令缓冲器中)
(2)寄存器
指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名
(3)段地址(SA)和 偏移地址(EA)
指令要处理的数据在内存中,在汇编指令中可用 [X] 的格式给出 EA, SA在某个段寄存器中。-
寻址方式小结
7764CF2E-C851-4F8A-91AD-C97887EB6A4E.png 指令要处理的数据有多长
- 8086CPU 可以处理两种尺寸的数据: byte word,所有的机器指令中 要指明 指令进行的是 字操作 还是 字节操作。
汇编语言处理方法如下:
(1)通过寄存器名指明要处理的数据尺寸;
(2)在没有寄存器名存在的情况下,用 X ptr 指明内存单元的长度。 X 在汇编指令中可以为 word 或 byte。
mov word ptr ds:[0],1
mov byte ptr ds:[0],1
(3)有些指令默认了访问字单元 还是 字节单元。 比如 push pop 只进行 字操作
assume cs:codesg,ds:datasg
datasg segment
db 'DEC'
db 'Ken Oslen'
dw 137
dw 40
db 'PDP'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov bx,0
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'
mov ax,4c00h
int 21h
codesg ends
end start
- div 指令
div 是除法指令,使用 div 做除法的时候注意以下问题:
(1)除数: 有 8位 和 16位 两种,在 一个 reg 或 内存单元中。
(2)被除数: 默认放在 AX 或 DX和AX 中。
如果除数位 8 位,被除数则为 16 位, 默认在 AX 中存放;
如果除数位 16 位,被除数则为 32位,在 DX 和 AX 中存放, DX 存放 高16位,AX 存放低16位。
(3)结果:
如果除数为 8位, 则 AL 存储 除法操作的 商,AH 存储除法操作的余数;
如果除数位 16位,则 AX 存储除法操作的商,DX存储除法操作的余数。
- 格式如下
div reg
dic 内存单元
/**
* (al) = (ax) / ((ds)*16+0)的商
* (ah)= (ax) / ( (ds*16) +0) 的余数
*/
div byte ptr ds:[0]
/**
* (ax) = ( (dx)*10000H + (ax) ) / ( (es)*16+0 )的商
* (dx) = ( (dx)*10000H + (ax) ) / ( (es)*16+0 )的余数
*/
div word ptr es:[0]
/**
* (al) = (ax) / ((ds)*16+(bx)+si+8)的商
* (ah)= (ax) / ((ds)*16+(bx)+si+8) 的余数
*/
div byte ptr [bx+si+8]
/**
* (ax) = ( (dx)*10000H + (ax) ) / ( (ds)*16+(bx)+si+8 )的商
* (dx) = ( (dx)*10000H + (ax) ) / ((ds)*16+(bx)+si+8)的余数
*/
div word ptr [bx+si+8]
伪指令 dd
db : 字节型 8位
dw:字型 16位
dd:dword(double word)双字型数据 32位dup
dup 是一个操作符,由编译器识别处理的符号。用来进行数据的重复。
格式:
db 重复次数 dup (重复的字节型数据)
dw 重复次数 dup (重复的字型数据)
dd 重复次数 dup (重复的双字型数据)
db 3 dup (0) //定义了3个字节,它们值都是0,相当于 db 0,0,0
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
db 3 dup ('abc','ABC') //定义了16个字节,它们是'abcABCabcABCabcABC' 相当于 db 'abcABCabcABCabcABC'
//定义一个容量为 200 个字节的 栈段
stacksg segment
db 200 dup (0)
stacksg ends
- 将 data 段中的数据按照格式写入到 table 段中,并计算 人均收入(取整):
assume cs:codesg,ds:datasg,es:table,ss:stack
datasg segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197524
dd 345890,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
datasg ends
table segment
db 21 dup ('year sumn ne ?? ')
table ends
stack segment
dw 8 dup (0)
stack ends
codesg segment
start: mov ax,stack
mov ss,ax
mov sp,10H
mov ax,datasg
mov ds,ax
mov ax,table
mov es,ax
mov bx,0
mov bp,0
mov si,0
mov cx,15H
s: push ds:[bx+si]
pop es:[bp]
push ds:[bx+si+2]
pop es:[bp+2]
push ds:54H[bx+si]
pop es:5H[bp]
push ds:54H[bx+si+2]
pop es:5H[bp+2]
push ds:0A8H[bx]
pop es:0AH[bp]
mov dx,es:5H[bp+2]
mov ax,es:5H[bp]
div word ptr es:0AH[bp]
mov es:0dH[bp],ax
add bp,10H
add bx,2H
add si,2H
loop s
mov ax,4c00H
int 21H
codesg ends
end start
运行结果如下:
B805AD8C-89AF-42E6-A8C0-315499ED0C6B.png