汇编06:包含多个段的程序
Posted 工作学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编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
以上是关于汇编06:包含多个段的程序的主要内容,如果未能解决你的问题,请参考以下文章