汇编语言(王爽)-包含多个段的程序


在操作系统环境中,合法的通过操作系统取得的空间都是安全的,在操作系统允许的情况下,程序可以取得任意容量的空间

程序取得所需空间的方法有两种:

  1. 加载程序时为程序分配

  2. 程序在执行过程中向系统申请


在代码段中使用数据

编程计算8个数据的和,结果存在ax寄存器中

1
0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

方法:将这些数据存放在一组地址连续的内存单元中,通过循环将数据累加到ax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
assume cs:code
code segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
mov bx,0
mov ax,0

mov cx,8
s: add ax,cs:[bx]
add bx,2
loop s

mov ax,4c00h
int 21h

code ends
end

dw用于定义字型数据,即define word

db用于定义字节型数据,即define byte

数据存在于代码段中,程序运行时CS存放代码段的段地址,所以从CS中得到数据的段地址

使用dw定义的数据处于代码段的最开始,所以数据的偏移地址为0,则8个数据处于代码段的偏移0、2、4、6、8、ACE处(每个数据是一个字,16位,一个内存单元8位),使用bx递增2实现循环

1.png

程序从0B3D:0000开始存放

使用u命令从0B3D:0000查看程序,前16个字节为dw定义的数据,从第16个字节开始才是汇编指令所对应的机器码

2.png

3.png

此时,程序执行的入口为定义的数据,并非第一条汇编指令,在Debug中可以通过设置IP来更改指令执行位置,在系统中直接执行可执行文件可能会出现问题

可以在源程序中指明程序入口的所在,使用end指令指明程序入口在标号start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
assume cs:code
code segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
start: mov bx,0
mov ax,0

mov cx,8
s: add ax,cs:[bx]
add bx,2
loop s

mov ax,4c00h
int 21h

code ends
end start

程序框架

1
2
3
4
5
6
7
8
9
10
11
assume cs:code
code segment

...数据...

start:

...代码...

code ends
end start

在代码段中使用栈

利用栈,将程序中定义的数据逆序存放

可以在程序中通过定义数据来取得一段空间,然后将这段空间当作栈空间来用

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
assume cs:codesg
codesg segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 # 定义16个字型数据,取得16个字的内存空间,将这段空间当作栈来使用

start: mov ax,cs
mov ss,ax
mov sp,30h ;设置栈顶ss:sp指向cs:30

mov bx,0
mov cx,8
s: push cs:[bx] ;将数据入栈
add bx,2
loop s

mov bx,0
mov cx,8
s0: pop cs:[bx] ;将数据出栈
add bx,2
loop s0

mov ax,4c00h
int 21h
codesg ends
end start

将数据、代码、栈放入不同的段

若数据、栈、代码所需的空间超过64KB,就不能放在一个段中(8086模式中,一个段的容量不能大于64KB)

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
assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends

stack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends

code segment
start: mov ax,stack
mov ss,ax
mov sp,20h

mov ax,data
mov ds,ax

mov bx,0

mov cx,8
s: push [bx]
add bx,2
loop s

mov bx,0

mov cx,8
s0: pop [bx]
add bx,2
loop s0

mov ax,4c00h
int 21h
code ends
end start

定义多个段的方法

对于不同的段,要有不同的段名

对段地址的引用

在程序中,段名相当于一个标号,代表了段地址

偏移地址要看数据在段中的位置,如0abch地址为data:6

段的安排

在源程序中为段起了具有含义的名称,仅用于使程序便于阅读

assume cs:code,ds:data,ss:stack将寄存器与相应的段相连,但assume是伪指令,由编译器执行,对CPU是透明的

CPU如何处理定义的段中的内容,完全依靠程序中具体的汇编指令和汇编指令对CS:IPSS:SPDS等寄存器的设置来决定

---------------The End---------------
0%