汇编语言笔记06-包含多个段的程序
转载必须注明出处,违者必究。http://www.cnblogs.com/dennisOne
在操作系统的环境下,合法地通过操作系统取得的空间都是安全的。程序取得所需空间的方法有两种:一是在加载程序的时候为程序分配,再就程序在执行过程中向系统申请。
对于第一种方式,我们在程序中定义将要处理的数据,这些数据被编译、连接程序作为程序的一部分写入可执行文件中。当可执行文件的程序加载到内存中,这些数据也同时被加载到内存中。
在代码段中使用数据
例:计算以下8个数据的和,结果存在ax寄存器中:
0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
1 assume cs:code 2 3 code segment 4 5 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 6 7 start: mov bx, 0 8 mov ax, 0 9 10 mov cx, 8 11 s: add ax, cs:[bx] 12 add bx, 2 13 loop s 14 15 mov ax, 4c00h 16 int 21h 17 18 code ends 19 end start ;通知编译器程序的入口,最终CS:IP指向该入口地址
debug分析: c:\codes>debug p6_2.exe -r AX=0000 BX=0000 CX=0026 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=0BDA ES=0BDA SS=0BEA CS=0BEA IP=0010 NV UP EI PL NZ NA PO NC 0BEA:0010 BB0000 MOV BX,0000 -u 0BEA:0010 BB0000 MOV BX,0000 0BEA:0013 B80000 MOV AX,0000 0BEA:0016 B90800 MOV CX,0008 0BEA:0019 2E CS: 0BEA:001A 0307 ADD AX,[BX] 0BEA:001C 83C302 ADD BX,+02 0BEA:001F E2F8 LOOP 0019 0BEA:0021 B8004C MOV AX,4C00 0BEA:0024 CD21 INT 21 DS=0BDA->CS=0BEA debug加载后,因为开头是数据(16bytes),end指定了start,所以将IP设置为10h,从而指向CS:IP的第一条指令。
在代码段中使用栈
例:使用栈将程序中定义的数据逆序存放。
1 assume cs:code 2 3 code segment 4 5 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 6 dw 0, 0, 0, 0, 0, 0, 0, 0 7 ; 用dw定义16个字型数据,在程序加载后,将取得16个字的内存空间, 8 ; 存放这16个数据。程序中将这段空间当做栈使用。 9 10 start: mov ax, cs 11 mov ss, ax 12 mov sp, 20h ; 设置栈顶ss:sp指向 cs:20 13 14 mov bx, 0 15 mov cx, 8 16 s: push cs:[bx] 17 add bx, 2 18 loop s ; 将0~15内存单元依次入栈 19 20 mov bx, 0 21 mov cx, 8 22 s0: pop cs:[bx] 23 add bx, 2 24 loop s0 ; 出栈 25 26 mov ax, 4c00h 27 int 21h 28 29 code ends 30 end start
将数据、代码、栈放入不同的段
将数据、栈和代码放到一个段里面,显得非常混乱;其次,由于8086的段最大为64kb, 如果将数据、栈都放在代码中,挤占了代码段的空间。
例:使用栈将程序中定义的数据逆序存放。
1 assume cs:code, ds:data, ss:stack 2 3 data segment 4 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 5 data ends 6 7 stack segment 8 dw 0, 0, 0, 0, 0, 0, 0, 0 9 stack ends 10 11 code segment 12 start: mov ax, stack 13 mov ss, ax 14 mov sp, 10h ; 设置栈顶ss:sp指向stack:10 15 16 mov ax, data 17 mov ds, ax 18 mov bx, 0 ; 设置ds:bx指向数据段的第一个单元 19 20 mov cx, 8 21 s: push [bx] 22 add bx, 2 23 loop s ; 入栈 24 25 mov bx, 0 26 mov cx, 8 27 s0: pop [bx] 28 add bx, 2 29 loop s0 ; 出栈 30 31 mov ax, 4c00h 32 int 21h 33 34 code ends 35 36 end start
注意:
- 伪指令"assumecs:code, ds:data, ss:stack"将cs、ds和ss分别和code、data、stack段相关联。但是伪指令是编译器执行的,cpu并不知道他们,所以并不会按照我们的意愿处理这些段。
- 源程序中的"end start"说明了程序的入口,入口被写入可执行文件的描述信息,可执行文件中的程序被加载入内存中,CPU的CS:IP被设置指向这个入口。