一段内存,既可以是代码存储空间,又是数据的存储空间,还可以是栈空间,也可以设么也不是,它们主要取决于cpu中寄存器的设置

  • CS(Code segment),IP(instruction pointer) :代码段
  • SS(stack segment),SP(stack pointer) :栈段
  • DS(date segment) :数据段

debug在修改寄存器ss时候,下一条指令也紧接着被执行例如:

1
2
3
mov ss,ax
mov ss,[0]
pop ss

汇编程序

汇编程源程序中有两类指令,一是汇编指令,第二是伪指令,汇编指令是有对应的机器码的指令,伪指令是由编译器来执行的。

目的 相关指令 指令性质 指令执行者
通知某一寄存器和程序中的某个段相联系 assume 寄存器:段名 伪指令 编译时,由编译期执行
通知编译器一个段开始 段名 segment 伪指令 编译时,由编译期执行
通知编译器一个段结束 段名 ends 伪指令 编译时,由编译期执行
程序返回 mov ax,4c00H int 21H 伪指令 编译时,由编译期执行
程序结束 段名 end 伪指令 编译时,由mov编译期执行

EXE文件加载

  1. 找到一段起始地址为SA:0000的容量足够的空闲内存区(复习操作系统中寻找内存空间的相关内容)

  2. 在这段内存前256字节中,创建一个程序段前缀(PSP)的数据区,DOS要利用PSP来和被加载程序进行通信

  3. 从这段内存的256字节出开始(PSP后面),将程序装入,程序地址被设为 SA+10H:0 ;

    空闲内存区: SA:0
    PSP区: SA:0
    程序区: SA+10H:0
    • PSP区和程序区虽然物理地址连续,但是却有不同的段地址
    • PSP头两个字节是 CD 20

    程序装入,程序的地址被设为SA+10H:0 (其中SA为系统为程序分配内存的起始位置的段地址,这个段地址被存放在DS寄存器当中,所以,从DS寄存器中可以得到PSP的段地址 )因为PSP占256字节(100H),所以程序的物理地址为 SA16+256 --> SA16+16*16 --> (SA+16)*16 --> SA+10H;
    debug后CS值比DS大10H,CS为代码段寄存器(程序区),DS为数据段(初始时==SA)

汇编文件编写及生成exe等文件

编写下列代码进入文件t1.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
assume cs:codesg

codesg segment

mov ax,2000H
mov ss,ax
mov sp,0
add sp,10
pop ax
pop bx
push ax
push bx
pop ax
pop bx

mov ax,4c00H
int 21H

codesg ends

end

  • 注意上面的add sp,10 10后面没有H(即不是10H),就代表这是十进制写法,sp=10–> sp=000a H

进行编译,链接 生成exe

1
2
masm ti.asm;
link t1.obj;

指令执行过程

push ax是入栈指令,在执行push ax时,cpu先将 SP=SP-2然后再将数据送入SS:SP指向的内存单元
pop ax是出栈指令,CPU先读取SS:SP处的数据,再SP=SP+2

指令学习

inc

inc bx 含义是bx中的内容加一

[bx]

[bx] : 类比[idata]的含义: DS中的数据段地址偏移量为idata处的值,则[bx]含义为将bx中的值作为偏移(段地址存在DS中)

1
mov ax,[bx]

功能: bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入ax中。即:((ds)*16+(bx))=(ax)

Loop

CPU执行Loop指令时要进行两步操作:
1. (cx)=(cx)-1
2. 判断cx中的值,不为零则转至标号处执行程序,如果为0则向下执行