文章目录
前言
参考书籍:
王爽。汇编语言。北京:清华大学出版社, 2013:1-1
本人菜狗一枚,不敢咬文嚼字,只能站在巨人的肩膀上窥探一下未曾了解的世界。
计算机进行数据处理和运算的两个基本问题
处理的数据在什么地方?
要处理的数据有多长?
描述性符号:
reg 表示寄存器
sreg 表示段寄存器
bx、si、di 和 bp
mov ax, [bx]
mov ax, [si]
mov ax, [di]
mov ax, [bx+si]
mov ax, [bx+di]
mov ax, [bx+si+idata]
mov ax, [bx+di+idata]
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+di] 含义:(ax) = ((ss) * 16 + (bp) + (di))
mov ax, [bp+si+idata] 含义:(ax) = ((ss) * 16 + (bp) + (si) + idata)
mov ax, [bp+di+idata] 含义:(ax) = ((ss) * 16 + (bp) + (di) + idata)
只要在 […] 中使用寄存器 bp,而指令中没有显性地给出段地址,段地址就默认在 ss 中。
机器指令处理的数据在什么地方
数据处理指令:
读取
写入
运算
机器指令不关心数据的值,而关心指令执行前一刻,它将要处理的数据所在位置
指令执行前数据可能存储的位置:
CPU 内部
内存
端口
机器码
汇编指令
指令执行前数据的位置
8E1E0000
mov bx, [0]
内存,ds:0 单元
89C3
mov bx, ax
CPU 内部,ax 寄存器
BB0100
mov bx, 1
CPU 内部,指令缓冲器
汇编语言中数据位置的表达
数据位置的表达
立即数(idata)
直接包含在机器指令中的数据(执行前在 CPU 指令缓冲器中)
立即数(idata)在汇编指令中直接给出
```
mov ax, 1
or bx, 00010000b
mov al, 'a'
```
寄存器
指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名。
```
mov ax, bx
mov ds, ax
push bx
mov ds:[0], bx
push ds
mov ss, ax
mov sp, ax
```
段地址(SA)和偏移地址(EA)
指令要处理的数据在内存中,在汇编指令中可用 [X] 的格式给出 EA, SA 在某个段寄存器中
存放段地址的寄存器是默认的,也可以显性给出
```
; 段地址默认在 ds 中
mov ax, [0]
mov ax, [di]
mov ax, [bx+8]
mov ax, [bx+si]
mov ax, [bx+si+8]
; 段地址默认在 ss 中
mov ax, [bp]
mov ax, [bp+8]
mov ax, [bp+si]
mov ax, [bp+si+8]
; 显性给出段地址
mov ax, ds:[bp]
mov ax, es:[bx]
```
寻址方式
寻址方式
EA
SA
名称
常用格式举例
[idata]
idata
(ds)
直接寻址
[idata]
[bx]
(bx)
(ds)
寄存器间接寻址
[bx]
[si]
(si)
(ds)
[di]
(di)
(ds)
[bp]
(bp)
(ss)
[bx+idata]
(bx) + idata
(ds)
寄存器相对寻址
用于结构体:[bx].idata
用于数组:idata[si]
用于二维数组:[bx][idata]
[si+idata]
(si) + idata
(ds)
[di+idata]
(di) + idata
(ds)
[bp+idata]
(bp) + idata
(ss)
[bx+si]
(bx) + (si)
(ds)
基址变址寻址
用于二维数组:[bx][si]
[bx+di]
(bx) + (di)
(ds)
[bp+si]
(bp) + (si)
(ss)
[bp+di]
(bp) + (di)
(ss)
[bx+si+idata]
(bx) + (si) + idata
(ds)
相对基址变址寻址
用于表格(结构)中的数组项:[bx].idata[is]
用于二维数组:idata[bx][si]
[bx+di+idata]
(bx) + (di) + idata
(ds)
[bp+si+idata]
(bp) + (si) + idata
(ss)
[bp+di+idata]
(bp) + (di) + idata
(ss)
指令要处理的数据有多长
处理数据的尺寸:byte 和 word
通过寄存器名指明要处理的数据的尺寸
寄存器指明进行字操作
mov ax, 1
mov bx, ds:[0]
mov ds, ax
mov ds:[0], ax
inc ax
add ax, 1000
寄存器指明进行字节操作
mov al, 1
mov al, bl
mov al, ds:[0]
mov ds:[0], al
inc al
add al, 100
在没有寄存器名存在的情况下,用操作符 X ptr 指明内存单元的长度,X 在汇编指令中可以为 word 或 byte
用 word ptr 指明指令访问的内存单元是一个字单元
mov word ptr ds:[0], 1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx], 2
用 byte ptr 指明指令访问的内存单元是一个字节单元
mov byte ptr ds:[0], 1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx], 2
其他方法
有些指明默认了访问的单元尺寸,如 push 指令只进行字操作
寻址方式的综合应用
【TODO】
div 指令
div 是除法指令
除数:8/16 位,在一个 reg 或 内存单元中
被除数:默认放在 AX 或 DX和AX中
除数为 8 位, 被除数则为 16 位,默认存放在 AX 中
除数为 16 位, 被除数则为 32 位,在 DX和AX 中存放,DX存放高 16 位, AX 存放低 16 位
结果:
除数为 8 位,则 AL 存储除法操作的商,AH 存储除法操作的余数
除数为 16 位, 则 AX 存储除法操作的商,DX 存储除法操作的余数
div reg
div 内存单元
汇编指令
商
余数
含义
div byte ptr ds:[0]
al
ah
(al) = (ax) / ((ds) * 16 + 0) 的商
(ah) = (ax) / ((ds) * 16 + 0) 的余数
div word ptr es:[0]
ax
dx
(ax) = [(ds) * 10000H + (ax)] / ((es) * 16+ 0) 的商
(ax) = [(ds) * 10000H + (ax)] / ((es) * 16+ 0) 的余数
div byte ptr [bx+si+8]
al
ah
(al) = (ax) / ((ds) * 16 + (bx) + (si) + 8) 的商
(ah) = (ax) / ((ds) * 16 + (bx) + (si) + 8) 的商
div word ptr [bx+si+8]
ax
dx
(ax) = [(dx) * 10000H + (ax)] / ((ds) * 16 + (bx) + (si) + 8) 的商
(dx) = [(dx) * 10000H + (ax)] / ((ds) * 16 + (bx) + (si) + 8) 的商
代码【TODO】
伪指令 dd
dd 是用来定义 dword(double word,双字)型数据的
data segment
db 1
dw 1
dd 1
data ends
在 data 段中定义了 3 个数据
第一个数据为 01H,在 data:0 处,占 1 个字节
第二个数据为 0001H,在 data:1 处,占 1 个字
第三个数据为 00000001H,在 data:3 处,占 2 个字
代码【TODO】
dup
dup 是一个操作符,同 db、dw、dd 等一样,也是由编译器处理识别的符号。
它是和 db、dw、dd 等数据定义伪指令配合使用的,用来进行数据的重复
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, 0, 1, 2
相当于 db 0, 1, 2, 0, 1, 2, 0, 1, 2
db 3 dup (‘abc’, ‘ABC’)
定义了 18 个字符, 它们是 ‘abcABCabcABCabcABC’
相当于 db ‘abcABCabcABCabcABC’
dup 的使用格式
db 重复的次数 dup (重复的字节型数据)
dw 重复的次数 dup (重复的字型数据)
dd 重复的次数 dup (重复的双字型数据)
dup 是一个十分有用的操作符
比如要定义一个容量为 200 个字节的栈段
stack segment
db 200 dup (0)
stack ends