汇编06:包含多个段的程序

包含多个段的程序

在执行汇编程序的时候,不要随便向某个寄存器中赋值,这可能会导致系统错误,虽然现在的操作系统已经完全把硬件保护起来了,但是在安全模式下还是可以执行导致系统崩溃的命令。所以我们在编写汇编程序的时候,要找到一段安全的空间供我们使用,在一般的PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用0:200到0:2ff的256个字节的空间,这就是一段安全空间。

我们有时需要编写含有多个段的程序,程序取得所需空间的方法有两种:加载程序的时候为程序分配、在程序执行的过程中向系统申请。这里我们只讨论第一种分配方式。

分离数据和代码

如果我们要完成一个功能:计算8个数据的和,结果存在ax寄存器中。

这个功能涉及到一个数据定义的过程,代码如下:

assume cs:code

code segment
	dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
	
	start:	mov bx,0
		mov ax,0
	s:	add ax,cs:[bx]
		add bx,2
		loop s
			
		mov ax,4c00h
		int 21h
code ends
end start

其中dw命令就是define word的意思,代表定义了8个字型数据,它们一共占16个字节。这些数据的地址分别是CS:0、CS:2...CS:E。

start和end start构成了一对,表明程序是从start的位置开始执行指令的,它用来标记程序入口,当程序被加载进内存时,CS:IP就会指向start标记的位置,然后开始执行。

也就是说在这个程序中,start上面是数据部分,下面是代码部分。

在代码段中使用栈

现在我们要完成一个功能:在数据定义好后,把上述8个数据利用栈在原位置逆序存放。这里我们必须开辟一片空间当做栈,我们依然可以用定义数据的方式来取得一段空间:

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
	
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					将8个数据依次入栈
		
	mov bx,0
	mov cx,8
s0:     pop cs:[bx]
	add bx,2
	loop s0					从栈中将数据取出放到最初的位置
		
	mov ax,4c00h
	int 21h					
codesg ends
end start

这里定义了16个0,其实根本用不了那么大的栈空间。栈顶指针ss:sp指向30,也就是指向已经定义了3个16字节的空间底部。

设置不同的段

前面的代码将所有内容都放到一个段中,这样做有两个主要的问题:

1、放到一个段中看起来很混乱

2、如果数据、栈和代码需要的空间超过64KB,就不能放在一个段中。

此时我们可以考虑设置多个段:

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			段名stack就代表段地址
		mov ss,ax			这里要让ss指向stack,因为不能直接对段寄存器赋值
						注意assume声明不代表寄存器就指向对应的段,还要手动设置
		mov sp,20h			设置栈顶ss:sp指向cs:20
		
		mov ax,data
		mov ds,ax			让ds指向data段地址
		mov bx,0
		mov cx,8
	s:	push [bx]
		add bx,2
		loop s				将8个数据依次入栈
		
		mov bx,0
		mov cx,8
	s0:     pop [bx]
		add bx,2
		loop s0				从栈中将数据取出放到最初的位置
		
		mov ax,4c00h
		int 21h					
code ends
end start
原文地址:https://www.cnblogs.com/yinyunmoyi/p/12811479.html