分段
- 问题1
- 8086是16位cpu,最多可以访问(寻址)多大内存?
- 问题2
- 8086允许最大内存1M,如何实现访问(寻址)到所有内存?
- 分段寻址
- 将内存划分成多段,通过段基址+段偏移的方式访问
- 计算方式
- 内存地址=段基址*10h+段偏移
- 例子:
- 名词
- 1. 段基址+段偏移 的方式一般写作 段地址:段偏移,称作逻辑地址
- 2. 偏移地址称作EA effective address
- 3. 通过逻辑地址计算出来的内存地址称作物理地址
- 问题
- 一个物理地址是否只能由一个逻辑地址表示?
- 可用内存
- dos系统值编程,应用程序可用内存约600K
- 段寄存器
- 8086中,段基址都是存储在段寄存器中,段偏移可以用立即数或者通用寄存器指明。
- 段超越:
- 8086寻址方式中,有一些默认段寄存器的情况。例如,如果用BP作为基址寻址的单元,则可表明此单元位于SS段;如果用BX作为基址寻址的单元,则可表明此单元位于DS段。但在某些特例下,需要进行段超越寻址,应使用段属性前缀。
例
- MOV CX,ES:[BX]
- 这条指令是把ES段中的偏移地址为BX的单元中的字送CX,而不是到DS段去寻址。
- 无论用BX,SI,DI或者BP作为间接寄存器,都允许段超越。
问题
- 1M的内存寻址需要多少根引脚?
操作码 [目的操作数][源操作数]
89C3 MOV BX,AX 1000 1001 1100 0011
89CB MOV BX,CX 1000 1001 1100 1011
89D3 MOV BX,DX 1000 1001 1101 0011
89DB MOV BX,BX 1000 1001 1101 1011
89E3 MOV BX,SP 1000 1001 1110 0011
89EB MOV BX,BP 1000 1001 1110 1011
89F3 MOV BX,SI 1000 1001 1111 0011
89FB MOV BX,DI 1000 1001 1111 1011
# mov [reg16],[reg16] 89...(11 后六位为两个寄存器编号)
# MOV BX,AX 1000 1001 1100 0011
#mov [reg],[reg]-> 1000 1001 11 000 011
#最后六个,前三个为源操作数寄存器编号,后三个为目标操作数寄存器编号
#与 [reg],[reg]的顺序相反
89C3 MOV BX,AX 1000 100 1 11 000 011
89CB MOV BX,CX 1000 100 1 11 001 011
89D3 MOV BX,DX 1000 100 1 11 010 011
89DB MOV BX,BX 1000 100 1 11 011 011
89E3 MOV BX,SP 1000 100 1 11 100 011
89EB MOV BX,BP 1000 100 1 11 101 011
89F3 MOV BX,SI 1000 100 1 11 110 011
89FB MOV BX,DI 1000 100 1 11 111 011
#寄存器对应编号
#ax cx dx bx sp bp si di
#000 001 010 011 100 101 110 111
mov si, di
1000 1001 1111 1110 89fe
#8位寄存器 mov操作
# mov [reg8],[reg8] 88...(11 后六位为两个寄存器编号)
88C7 MOV BH,AL 1000 1000 1100 0111
88E7 MOV BH,AH 1000 1000 1110 0111
88DF MOV BH,BL 1000 1000 1101 1111
88FF MOV BH,BH 1000 1000 1111 1111
88CF MOV BH,CL 1000 1000 1100 1111
88EF MOV BH,CH 1000 1000 1110 1111
88D7 MOV BH,DL 1000 1000 1101 0111
88F7 MOV BH,DH 1000 1000 1111 0111
88C7 MOV BH,AL 1000 100 0 11 000 111
88E7 MOV BH,AH 1000 100 0 11 100 111
88DF MOV BH,BL 1000 100 0 11 011 111
88FF MOV BH,BH 1000 100 0 11 111 111
88CF MOV BH,CL 1000 100 0 11 001 111
88EF MOV BH,CH 1000 100 0 11 101 111
88D7 MOV BH,DL 1000 100 0 11 010 111
88F7 MOV BH,DH 1000 100 0 11 110 111
#8位寄存器 mov操作
# mov [reg8],[reg8] 88...(11 后六位为两个寄存器编号)
#al cl dl bl ah ch dh bh
#000 001 010 011 100 101 110 111
89FE MOV SI,DI 1000 1001
88FE MOV DH,BH 1000 1000
89C3 MOV BX,AX 1000 10 0 1 11 000 011
89CB MOV BX,CX 1000 10 0 1 11 001 011
89D3 MOV BX,DX 1000 10 0 1 11 010 011
89DB MOV BX,BX 1000 10 0 1 11 011 011
89E3 MOV BX,SP 1000 10 0 1 11 100 011
89EB MOV BX,BP 1000 10 0 1 11 101 011
89F3 MOV BX,SI 1000 10 0 1 11 110 011
89FB MOV BX,DI 1000 10 0 1 11 111 011
88C7 MOV BH,AL 1000 10 0 0 11 000 111
88E7 MOV BH,AH 1000 10 0 0 11 100 111
88DF MOV BH,BL 1000 10 0 0 11 011 111
88FF MOV BH,BH 1000 10 0 0 11 111 111
88CF MOV BH,CL 1000 10 0 0 11 001 111
88EF MOV BH,CH 1000 10 0 0 11 101 111
88D7 MOV BH,DL 1000 10 0 0 11 010 111
88F7 MOV BH,DH 1000 10 0 0 11 110 111
#注意: 如 1000 1011 0000 0111 后8位中的前两位解析:
#00表示mov 的操作数为内存到寄存器(无常量),
#01表示内存到寄存器(跟一个8位的立即数),
#10表示内存到寄存器(跟一个16位的立即数),
#11表示寄存器到寄存器
8B07 MOV AX,[BX] 1000 10 1 1 00 000 111
8B05 MOV AX,[DI] 1000 10 1 1 00 000 101
8B03 MOV AX,[BP+DI] 1000 10 1 1 00 000 011
8B00 MOV AX,[BX+SI] 1000 10 1 1 00 000 000
8B4212 MOV AX,[BP+SI+12] 1000 10 1 1 01 000 010 disp8
8B825634 MOV AX,[BP+SI+3456] 1000 10 1 1 10 000 010 disp16
8A825634 MOV AL,[BP+SI+3456] 1000 10 1 0 10 000 010 disp16
8B817856 MOV AX,[BX+DI+5678] 1000 10 1 1 10 000 001 disp16
89817856 MOV [BX+DI+5678],AX 1000 10 0 1 10 000 001 disp16
#另外,第七位是0或者1,表示的是数据的来源是寄存器还是内存(目的操作数)
#第八位为0表示操作数的位数为8位,为1表示操作位的位数为16位
//a 1010 b 1011 c 1100 d 1101 e 1110 f 1111
C6870005FF
mov byte [bx+500],ff
1100, 0110, 10(mod) 00, 0111, 0000, 0000,0000, 0101, 1111, 1111
C607ff
mov byte [bx],ff
1100, 0110, 00(mod) 00, 1001, 1111, 1111
C64710FF
mov byte ptr [bx+10],ff
1100, 0110, 01(mod) 00, 1001, 0001, 0000, 1111, 1111
883f
mov byte ptr [bx],bh
1000, 1000, 00(mod) 11, 1111
mov指令总结
MOV指令机器码及其解析
MOV = Move 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
寄存器/内存->寄存器/内存 1 0 0 0 1 0 d w mod reg r/m ;
立即数 -> 寄存器/内存 1 1 0 0 0 1 1 w mod 0 0 0 r/m data data if w = 1
立即数 -> 寄存器 1 0 1 1 w reg data data if w = 1 ;
内存 -> 累加器 1 0 1 0 0 0 0 w addr-low addr-high ;
累加器 -> 内存 1 0 1 0 0 0 1 w addr-low addr-high ;
寄存器/内存-> 段寄存器 1 0 0 0 1 1 1 0 mod 0 Sreg r/m ; Sreg表示段寄存器
段寄存器 -> 寄存器/内存 1 0 0 0 1 1 0 0 mod 0 Sreg r/m ;
解释:第一列表示数据从 源操作数->目的操作数
reg/m 它们都是有三位二进制数表示,寄存器是有对应编号(8位和16位要看w的值),内存是要有以下几种组合:
[reg] [reg+reg] [reg+imm] [reg+reg+imm];其中reg,reg+reg所对应的有编号 有立即数的话后面就要跟立即数的数据
w表示的是操作数是16位还是8位,w=1表示操作数是16,w=0表示操作数是8位的,由于8位寄存器和16位都是由3位二进制
数来进行编码的,因此需要以此区分。(通用寄存器,段寄存器不存在这种区分)
d表示数据来源是内存还是寄存器 d=0表示数据来源是寄存器,d=1表示数据来源是内存
mod 指的是那种方式,由2位二进制数据来表示,
00表示[EA]中无常量
01表示[EA]中常量单字节
10表示中常量双字节
11表示寄存器操作
reg通用寄存器对应编码:
16位通用寄存器:
ax cx dx bx sp bp si di
000 001 010 011 100 101 110 111
8位寄存器:
al cl dl bl ah ch dh bh
000 001 010 011 100 101 110 111
Sreg段寄存器对应编码:
es cs ss ds
00 01 10 11
#[EA] 内存对应
000 EA = BX+SI + DISP
001 EA = BX+DI + DISP
010 EA = BP+SI + DISP
011 EA = BP+DI + DISP
100 EA = SI + DISP
101 EA = DI + DISP
110 EA = BP + DISP
111 EA = BX + DISP
作业:实现以下指令的汇编和反汇编
mov r16, r16 OK
mov r8, r8 OK
mov r16, [EA] OK
mov r8, [EA] OK
mov [EA], r16 NO
mov [EA], r8 NO
mov r8, imm8 OK
mov r16, imm16 OK
mov [EA], imm8 部分
mov [EA], imm16 部分