汇编语言笔记6包含多个段的程序

汇编语言笔记6包含多个段的程序

0x00 为什么需要多个段

​ 在操作系统环境中,有两种取得空间方式,一在加载程序时为程序分配,二是在程序执行过程中向系统申请,前者称为静态分配,后者称为动态分配。

​ 我们通过在源程序中定义段来进行内存空间的获取。另外我们一般定义不同的段来分别处理数据 代码 栈空间

​ 因此我们得在代码中定义多个段

0x01 只使用一个段得情况

1在代码段定义数据

​ 我们可以在代码段定义数据,这样这些数据就随着代码一起被装入内存了

assume cs:code
code segment
		dw 0123h,0456h,0789h
start:	mov bx,0
		mov ax,0
		mov cx,3
		mov dx,start
s:		add ax,cs:[bx]
		add bx,2
		loop s
		mov ax,4c00h
		int 21h
code ends
end start

​ 上述代码的作用是将三个数累加到ax中,在代码的最开始我们通过dw 定义了三个字型数据 数据之间用逗号分隔 同理db定义字节数据

​ 由于定义在代码段的最开始,所以这三个字型数据的偏移地址分别是 0 2 4,段地址则是cs 所以bx初始为0

​ 那么我们在代码段定义了数据 而ip初始为0 程序执行的指令会发生异常,因为指令的偏移地址不是0,那怎么办呢? 使用 start 和 end start标号,将ip初始到start对应的地址 ,表示指令从哪儿开始执行,哪儿结束

​ 上述代码中 我们试着将start的内容mov到dx(这条指令在编译时被给了一个warning),因为我们知道标号在编译时会被解释为一个地址,让我们看看start的地址和ip是不是一致的

QQ截图20200530103134

QQ截图20200530103201

​ 经过编译链接调试我们看到 ip 确实被初始化到start 6这里了,为什么第一条指令的偏移地址是6呢? 因为我们在代码段的开头定了三个字型,一共占6个字节 所以偏移地址是6

2在代码段使用栈

QQ截图20200530103719

assume cs:codesg
codesg segment
		dw 0123h,0456h,0789h
		dw 0,0,0
start:	mov ax,cs
		mov ss,ax
		mov ds,ax
		mov sp,0ch
		mov bx,0
		mov cx,3
s:		mov ax,ds:[bx]
		push ax
		add bx,2
		loop s
		mov ax,4c00h
		int 21h
codesg ends
end start

上述代码和标准答案不一样 主要在 标答的数据是8个字型 栈空间也是8个字型,sp赋值30h 按道理说 我的代码只是标答的精简版应该也是对的,但是我的代码结果怎么都错,不能正常的将三个数据倒序赋值到 后面的三个字型的空间里,为什么呢

经过逐步执行,发现问题出现在栈的初始化执行中 设置 ss和sp这一步后,栈空间会被随机初始化,而把前面三个字型的数据空间也改了,所以错了,而标答对了大概是它给栈空间比较大,不会改到数据区

QQ截图20200530105634

0x02 检测点

QQ截图20200530110158

​ mov cs:[bx],ax

QQ截图20200530110341

​ mov ax,cs

​ mov sp,24h//2020-6-26改正:栈的第一个元素起始地址是36-1=35,转换成16进制是22h,所以栈空则是+2 24h

​ pop cs:[bx]

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

​ 在前面的内容中,我们将 数据 栈 代码放到一个段里,这样显得混乱,而且如果数据+栈+代码不能超过64k 十分受限

​ 所以 我们通过定义多个段来解决这一问题

assume cs:code,ds:data,ss:stack
data segment
		dw 0123h,0456h
data ends
stack segment
		dw 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 ax,4c00h
		int 21h
code ends
end start

​ 上述代码的功能是将数据段的8个字型数据倒入push进栈

​ 1 我们如同定义代码段一样的方法定义数据段和栈段

​ 2 我们可以直接对段地址引用 如 mov ax,data 因为我们知道标号最红会被解释成一个idata地址,mov 不能直接将idata送入段寄存器 所以才先送入ax

​ 3 这些段 是我们写程序时自己的安排,并不因 ss:stack 这样的写法就自动将stack的地址写入ss 还需要我们在代码段中改写ss (但是奇怪的时cs却能被cs:code 自动修改。。。。)

QQ截图20200530111739

QQ截图20200530111756