这4个
寄存器可以用在[...]
中来进行内存单元的寻址
。这4个
寄存器都可以单独使用。bx
或 bp
。在实现更复杂的内存寻址时,用 si
或di
与 bx
或bp
组合。立即数
。bx
与 bp
, si
与di
不能直接组合 )寄存器 | 单独使用 | 与si 组合 | 与 di 组合 | 与立即数 组合 |
---|---|---|---|---|
bx | [ bx ] | [ bx + si ] | [ bx + di ] | [ bx + idata ] [ bx + si + idata ] |
pb | [ pb ] | [ pb + si ] | [ pb + di ] | [ pb + idata ] [ pb + si + idata ] |
bx
时默认的段地址在 ds
,如:mov ax, [bx]
; mov ax, [bx+si]
; mov ax, [bx+si+idata]
bp
时默认的段地址在 ss
,如:mov ax, [bp]
; mov ax, [bp+si]
; mov ax, [bp+si+idata]
mov ax, es:[bx]
; mov ax, es:[bx+si]
; mov ax, es:[bx+si+idata]
mov ax, cs:[bx]
; mov ax, cs:[bx+si]
; mov ax, cs:[bx+si+idata]
。3 个地方:CPU内部
、内存
、接口
(将在后面的课程中进行讨论)
机器码 | 汇编指令 | 指令执行前数据的位置 |
---|---|---|
8E1E0000 | mov bx,[0] | 内存,ds:0 单元 |
89C3 | mov bx,ax | CPU 内部,ax 寄存器 |
BB0100 | mov bx,1 | CPU 内部,1 在指令缓冲器中 |
汇编语言中用 3 个概念来表达数据的位置
直接写在代码
中的数据,在汇编语言中称为: 立即数
。(它们执行前在 CPU 的指令缓冲器中)
可以简单的理解为汇编语言的字面量
(只是类似,不是同相)。
mov ax,1
add bx,2000h
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
要处理的数据在内存
时,汇编指令中可用[X]
的格式指出 EA、SA
在某个段寄存器中。
计算
内存单元偏移地址
的方法
称为寻址方式
。
8086CPU指令,可以处理 byte
(8位) 和 word
(16位) 两种尺寸的数据。
寄存器名
知晓数据的尺寸。使用AX、BX、CX、DX
这些16位寄存器,说明数据尺寸为字
,如:
mov ax,1
mov bx,ds:[0]
mov ds,ax
mov ds:[0],ax
inc ax
add ax,1000
使用ah、al、bh、bl、ch、cl、dh、dl
这些8位寄存器,说明数据尺寸为字节
,如:
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
2000:1000 FF FF FF FF FF FF ......
byte ptr
修改 2000:1000 位置结果为2000:1000 01 FF FF FF FF FF ......
word ptr
修改 2000:1000 位置结果为2000:1000 01 00 FF FF FF FF ......
有些指令默认了访问的是字
单元还是字节
单元,
比如:push [1000H]
无需指明访问数据的尺寸,因为 push
指令只进行字
操作。
8086CPU提供了[bx+si+idata]
的寻址方式,便于结构化数据
的处理。
bx
:定位整个结构体,idata
:定位结构体中的某一个数据项si
:定位数组项中的每个元素。且汇编语言提供了更为贴切的书写方式,如:[bx].idata
、[bx].idata [si]
。
对应C语言中的变量.数据项[字符]
。如书中的C代码示例声明了这样一个结构体:
struct company { /*声明一个公司记录的结构体*/
char cn[3]; /*公司名称*/
char hn[9]; /*总裁姓名*/
int pm; /*排名*/
int sr; /*收入*/
char cp[3]; /*著名产品*/
}
/*定义一个公司记录的变量,内存中将存有一条公司的记录*/
struct company dec={ "DEC", "Ken Olsen", 137, 40, "PDP" };
8
或16
位。可放存在寄存器
或内存
。16
或32
位。16位
,放在AX
中。如果32位
,高16位
在DX
。DIV
操作中被除数
是用16
还是32
取决于除数
用多少位来运算:8位
则被除数16位
,16位
则被除数32位
。被除数 | 位数 | AX | DX |
---|---|---|---|
2 | 16位 | 00000000 00000010 | |
65536 | 32位 | 00000000 00000000 | 00000000 00000001 |
除数
用多少位来运算。8位
则。AL
存商
,AH
存余数
。16位
则。AX
存商
,DX
存余数
。除数 | 商 | 余数 |
---|---|---|
8位 | AL | AH |
16位 | AX | DX |
缩写 | 全称 | 含义 | 位数 |
---|---|---|---|
db | define byte 或 data byte | 定义字节(1个字节)的数据 | 8 |
dw | define word 或 data word | 定义字(2个字节)的数据 | 16 |
dd | define doubleword 或 data doubleword | 定义双字(4个字节)的数据 | 32 |
用 div
计算 data
段中第一个数据除以第二个数据后的结果,商存在第三个数据的存储单元中。
data segment
dd 100001 ; 被除数 dword(双字)型 32 位
dw 100 ; 除数 word ( 字 )型 16 位
dw 0 ; 存商的位置
data ends
data
段中 dd
定义是被除数,做除法之前:data:0
字单元中的低 16 位存储在 ax
中data:2
字单元中的高 16 位存储在 dx
中mov ax,data
mov ds ,ax
mov ax,ds:[0] ; ds:0 双字单元中的低 16 位存储在 ax 中
mov dx,ds:[2] ; ds:2 双字单元中的高 16 位存储在 dx 中
div word ptr ds:[4] ; 用 dx:ax 中的 32 位数据除以 ds:4 字单元中的数据
mov ds :[6],ax ; 将商存储在 ds:6 字单元中
assume cs:codesg, ds:data
data segment
dd 100001 ; 被除数 dword(双字)型 32 位
dw 100 ; 除数 word ( 字 )型 16 位
dw 0 ; 存商的位置
data ends
codesg segment
mov ax,data ; 设置代码段位置。先用 ax 中转一手,才能装入 ds
mov ds,ax
; 读取 32位 双字节 被除数存入寄存器 dx:ax
mov ax,ds:[0] ; 从 ds:0 处开始读取低 16 位 '86A1' 存入 ax 中
mov dx,ds:[2] ; 从 ds:2 处开始读取高 16 位 '0001' 存入 dx 中
div word ptr ds:[4] ; 用 dx:ax 中的 32 位数据除以 ds:4 字单元中的数据
mov ds:[6],ax ; 将商存储在 ds:6 字单元中
codesg ends
end
u cs:0 002F
查看从程序开始到 002F
部分反编译结果。
CS:0000H
处开始执行。-u
命令忘记了的话要可以回顾一下:Debug的使用-u
命令查看反汇编结果时,可以看到数据段
部分也显示了对应的汇编代码
,但这只是debug
自作多情罢了。因为这段内容只会被当作数据
读取。虽然可以一根筋的把它翻译成汇编代码,但是然并卵,它只是一段数据。dd 100001
另外两个同理。100001
转16进制后是 186A1
00 01 86 A1
A1 86 01 00
dup
操作符在汇编语言中是一个用于简化定义重复数据
的操作符。
它通常与数据定义伪指令(如 db、dw、dd 等)结合使用,以指定重复特定模式的数据块的次数
指令 | 描述 | 生成的数据 |
---|---|---|
db 5 dup(0) | 定义5个字节,每个字节的值都为0 | 00 00 00 00 00 |
dw 3 dup(0x1234) | 定义6个字节(因为dw 是定义字,占两个字节),每个字的值都是0x1234 | 34 12 34 12 34 12 |
dd 2 dup(0x12345678) | 定义8个字节(因为dd 是定义双字,占四个字节),每个双字的值都是0x12345678 | 78 56 34 12 78 56 34 12 |
db 4 dup(1, 2, 3) | 定义12个字节,按照序列1、2、3重复四次 | 01 02 03 01 02 03 01 02 03 01 02 03 |
———————————— |