汇编语言---------王爽第6章


在操作系统的环境中,合法通过操作系统取得的空间都是安全的。程序取得所需要空间的方法有两种,一是在加载程序的时候为程序分配,二是程序在执行的过程中向系统申请。我们可以用 dw xxxxxh来申请内存空间,dw的含义是定义字型数据。dw即"define word"的意思。需要注意的是如果我们直接用dw来申请内存空间可能会导致直接运行汇编程序时出错,因为数据和指令本质上都是二进制数据罢了。所以我们需要在源程序中指明程序的入口所在,具体做法就是在指令开始的语句前加个 start标记,然后再程序结尾用 end start告诉程序入口到底在哪。

start:





end start

那么程序时如何知道程序入口在哪的呢 end start伪指令通过把标记转为偏移地址的方法 将ip改变为程序入口的偏移地址。
所以我们应该考虑设置多个段存放不同的内容。

如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为(N/16 +1)*16,因为8086CPU规定一个段的起始地址为16的倍数,

在代码段中使用数据

考虑这样一个问题,编程计算以下8个数据的和,结果存在ax寄存器中:
0123h、0456h、0789h、0abch、0defg、0fedh、0cbah、0987h
之前我们不关心数据本身,但是现在指定了数据给我们累加所以需要关心数据本身,那么我们需要给这些数据安排一些存储空间,我们不能随意指定存储空间,最安全的方式是随着程序的加载让CPU给我们自动安排存储空间。当可执行文件中的程序被加载入内存时,这些数据也同时被加载入内存中。
具体做法可以看下面的程序:

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

但是这样写的程序会有些问题,第一便是程序结构太混乱,代码和数据都放在一个段中,第二便是如果我们之间执行程序,那么便会出现问题,因为程序前面是数据而不是指令。
我们有解决方法在源程序中直接指明程序的入口所在,具体做法如下:

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

我们可以探讨下end的作用,end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方,在上面的程序中我们用end 指令指明了程序的入口在标号start处。
那么程序时如何知道程序入口在哪的呢 end start伪指令通过把标记转为偏移地址的方法 将ip改变为程序入口的偏移地址既标记所在代码的偏移地址。归根结底,我们若要CPU从何处开始执行程序,只要在源程序中用“end 标号”指明就可以了。

在代码段中使用栈

如果我们要将一些数据按逆序存放,那么可能我们需要使用到栈。如何在代码段中使用栈呢,请看下面的程序:

assume cs:codesg

code 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

		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

我们在程序中用dw定义了16个为0的字型数据,我们把这16个字型数据所占的存储空间当作栈来使用,只要我们让ss指向字型数据所在段,sp指向栈底便可以了。

检测点6.1

assume cs:codesg

codesg segment
	dw 0123h,0456h,0789h,0abch,0defh,0cbah,0987h

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

			mov ax,4c00h
			int 21h
codesg ends

end start

(2)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行。栈空间设置在程序内。完成程序:

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

start:	mov ax,cs
			mov ss,ax
			mov sp,24h

			mov ax,0
			mov ds,ax
			mov bx,0
			mov cx,8
s:			push [bx]
			pop cs:[bx]
			add bx,2
			loop s

			mov ax,4c00h
			int 21h
codesg ends

end start

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

我们之前在程序中用到了数据和栈,将数据、栈和代码都放到一个段里面,我们可以把栈空间和数据和指令都放在一个代码块中,但是这样使用会带来一些问题,比如一个代码块的大小最都为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
			mov ss,ax
			mov sp,20h

			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

代码段、数据段、栈段完全是我们的安排,如何让CPU按照我们的这种安排来执行这个程序呢,我们在源程序中使用伪指令assume cs:code,ds:data,ss:stack将cs、ds和ss分别相连但是这样做并没有真的让CPU按照我们的意图来执行程序。所以我们需要在代码段中利用汇编指令设置ds和ss里的内容将它正确指向相应的段。
下面我们解读下程序:

对段地址的引用

程序中有多个段了,如何访问段中的数据呢,我们可以通过地址来访问段中的数据,而地址是分为两部分的既段地址和偏移地址,如何指明要访问的数据的段地址呢,在程序中,段名就相当于一个标号,它代表了段地址,所以指令“mov ax,data”的含义就是将data段的段地址送入ax中,偏移地址就是在data段中的偏移地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值