第一章 基础知识

检测点1.1

  1. 13
  2. 1024 0 1023
  3. 8192 1024
  4. 1073741824 1048576 1024
  5. 64 1 16 4
  6. 1 1 2 2 4
  7. 512 256
  8. 二进制

寄存器

检测点2.1

检测点2.1.1

指令 AX BX CX 备注
mov ax, 62627 F4A3H - - 62627(十进制) = F4A3H
mov ah, 31H 31A3H - - 只改 AH,AL 保持 A3H
mov al, 23H 3123H - - 只改 AL,AH 保持 31H
add ax, ax 6246H - - 3123H + 3123H = 6246H
mov bx, 826CH 6246H 826CH - BX 赋值
mov cx, ax 6246H 826CH 6246H CX ← AX
mov ax, bx 826CH 826CH 6246H AX ← BX
add ax, bx 04D8H 826CH 6246H 826CH + 826CH = 104D8H,高位舍弃
mov al, bh 0482H 826CH 6246H AL ← BH(82H),AH 保持 04H
mov ah, bl 6C82H 826CH 6246H AH ← BL(6CH),AL 保持 82H
add ah, ah D882H 826CH 6246H AH = 6CH + 6CH = D8H,AL 不变
add al, 6 D888H 826CH 6246H AL = 82H + 6H = 88H,AH 不变
add al, al D810H 826CH 6246H AL = 88H + 88H = 10H(进位舍弃),AH 不变
mov ax, cx 6246H 826CH 6246H AX ← CX,恢复为 6246H

说明: 加粗表示该寄存器在本条指令中发生了改变。最后一列备注解释了运算或操作过程。

检测点2.1.2

mov ax, 2
add ax, ax
add ax, ax
add ax, ax

检测点2.2

  1. 00010H-1000FH
  2. 最小1001H 最大2000H
  3. 当段地址<=1000H或段地址>=2001H时CPU无论怎么变化偏移地址都无法寻到20000H单元

问题2.3

B8 22 66 EA 03 00 00 10 B8 00 00 8B D8 FF E3 B8 23 01 …循环

检测点2.3

四次修改IP

第一次:mov ax, bx指令进入指令缓冲器后
第二次:sub ax, ax指令进入指令缓冲器后
第三次:jmp ax指令进入指令缓冲器后
第四次:jmp ax指令执行完毕后

最后的值为0

寄存器(内存访问)

问题3.1

  1. 0地址单元存放的字节型数据为20H
  2. 0地址字单元存放的字型数据为4E20H, 即起始地址为0的字单元
  3. 2地址单元存放的字节型数据为12H
  4. 2地址字单元存放的字型数据为0012H, 即起始地址为2的字单元
  5. 1地址字单元存放的字型数据为124EH, 即起始地址为1的字单元

问题3.2

ds寄存器存放的是段地址 [0]表示偏移为0

1
2
3
mov bx,1000H
mov ds,bx
mov [0],al

问题3.3

  • ax=1123
  • bx=8833
  • cx=8833

扩展:

用纸笔自己推一下数据在内存中是如何变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mov ax,32h
mov bx,1000h
mov ds,bx
mov [0],ax
add ax,1
mov [1],ax
add ax,1
mov [2],ax

mov ax,[0]
mov bx,[2]
mov cx,[1]
mov bx,[1]
mov cx,[2]

最终结果:

  • ax=3332
  • bx=3433
  • cx=0034

问题3.4

1000:0 34 2C 12 1B

检测点3.1

检测点3.1.1

提示: 根据段地址+偏移找内存值的时候不能只局限于段地址和偏移本身, 要看背后计算出来的物理地址

即:0001:0000 = 0000:0010

1
2
3
4
5
6
7
8
9
10
11
12
AX=2662
BX=E626
AX=E626
AX=2662
BX=D6E6
AX=FD48
AX=2CE4
AX=0000
AX=00E6
BX=0000
BX=0026
AX=000C

注意:寄存器在内存中是怎么表示的

检测点3.1.2

注意: CSDS并不一样, 一个是当前代码的source point, 一个是当前数据的source point

CS=2000H, IP=0, DS=1000H, AX=0, BX=0

  1. mov ax,6622H
    执行后CS=2000H, IP=0003H, DS=1000H, AX=6622H, BX=0
  2. jmp 0ff0:0100
    执行后CS=0ff0H, IP=0100H, DS=1000H, AX=6622H, BX=0
  3. mov ax,2000H ;
    执行后CS=0ff0H, IP=0103H, DS=1000H, AX=2000H, BX=0
  4. mov ds,ax
    执行后CS=0ff0H, IP=0105H, DS=2000H, AX=2000H, BX=0
  5. mov ax,[0008]
    执行后CS=0ff0H, IP=0108H, DS=2000H, AX=C389H, BX=0
  6. mov ax,[0002]
    执行后CS=0ff0H, IP=010EH, DS=2000H, AX=EA66H, BX=0
  7. mov ax,6622H
    执行后CS=0ff0H, IP=0111H, DS=1000H, AX=6622H, BX=0
  8. jmp 0ff0:0100
    执行后CS=0ff0H, IP=0100H, DS=1000H, AX=6622H, BX=0
  9. mov ax,6622H
    执行后CS=0ff0H, IP=0103H, DS=1000H, AX=6622H, BX=0

数据和程序没有区别, 被CS:IP指向的内存信息是程序, 被DS:偏移指向的内存信息是数据

问题3.6

当栈有一个子单元时SP为000EH, 那么pop后栈空时SP+2=0010H

所以SP为0010H

问题3.7

栈范围: 10000H-1000FH
初始栈为空
将ax,bx,ds中的数据入栈

1
2
3
4
5
6
mov ax,1000H
mov ss,ax
mov sp,0010H
push ax
push bx
push ds

问题3.8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mov ax,1000H
mov ss,ax
mov sp,0010H

mov ax,001AH
mov bx,001BH

push ax
push bx

mov ax,0
;也可以是sub ax,ax
mov bx,0
;也可以是sub bx,bx

pop bx
pop ax

问题3.9

1
2
3
4
5
6
7
8
9
mov ax,1000H
mov ss,ax
mov sp,0010H
mov ax,001AH
mov bx,001BH
push ax
push bx
pop ax
pop bx

问题3.10

1
2
3
mov ax,1000H
mov ss,ax
mov sp,0002H

知识点: 注意出栈的过程, 是先改变SP的值再在SP处写入数据所以如果要显示的写入某个地址时, 应该把SP设置到偏移地址+2处

问题3.11

SP=0

问题3.12

00000H - FFFFFH

检测点3.2

检测点3.2.1

1
2
3
mov ax,2000H
mov ss,ax
mov sp,0020H

检测点3.2.2

1
2
3
mov ax,1000H
mov ss,ax
mov sp,0

实验2.2.1

注意:值不唯一,根据运行结果填入即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
ax=C0EA
ax=0012
bx=30f0
bx=2F31

;执行push ax前:
;ss=2200
;sp=0100
;栈顶地址为: 22100

;执行push ax时:
;先sp-2: sp=00fe, 栈顶地址为220fe
;再把寄存器ax中的值放入栈顶, 所以修改的内存单元地址为220fe(2200:00fe), 内容为0012

;执行push bx时:
;先sp-2: sp=00fc, 栈顶地址为220fc
;再把寄存器bx中的值放入栈顶, 所以修改的内存单元地址为220fc(2200:00fc), 内容为2f31

;执行pop ax时:
;先把栈顶220fc(2200:00fc)的值放入寄存器ax, ax=2f31
;再把sp+2, sp=00fe, 栈顶地址为220fe(2200:00fe)

;执行pop bx时:
;先把栈顶220fe(2200:fe)的值放入寄存器bx, bx=0012
;再把sp+2, sp=0100, 栈顶地址为22100(2200:0100)

;push [4]时:
;先把sp-2: sp=00fe, 栈顶地址为220fe
;再把数据段地址[4]中的值放入栈顶, 所以修改的内存单元地址为220fe(2200:00fe), 内容为30F0

;push [6]时:
;先把sp-2: sp=00fc, 栈顶地址为220fc
;再把数据段地址[6]中的值放入栈顶, 所以修改的内存单元地址为220fc(2200:00fc), 内容为2F31


实验2.2.2

1
2
3
4
5
6
7
mov ax,2000H
mov ss,ax
mov sp,0010H
mov ax,3123
push ax
mov ax,3366
push ax

思考: 执行完mov ss,ax和mov sp,10后为什么2000:0 ~ 2000:f的值会发生变化:

因为debug利用了cpu的中断机制, 当中断发生时, cpu会将flags, cs和ip压入栈顶

1
2000:0000 00 00 00 00 23 31 00 20-00 00 08 01 3f 07 a3 01

当使用t执行mov sp,10后, 当前栈顶就指向了2000FH, 因为t命令会触发cpu的中断, 所以cs和ip被压入栈顶
并在2000:0处显示出来