[从零学习汇编语言] - 数据段与内存

前言

点赞再看,养成习惯!

该系列博文基于王爽老师 <汇编语言 第四版> 一书,需要的同学链接自取:

链接:https://pan.baidu.com/s/1NAgD1Z15LtK1BuH92xmICA
提取码:xlzb

另外书中提到的DosBox软件不想去官网下载的小伙伴也可以自取:

链接:https://pan.baidu.com/s/1O6PnLb_hN-WUS2avicNpcw
提取码:xlzb

最后如果还没有计算机基础的同学,建议先补充下计算机相关的基础知识:

笔记目录总览

一、内存与数据段

1. 栈内存与E指令

我们先提出一个问题:如果我们想要计算1+2+3,我们应该怎么做?

# 这个问题应该算是一个比较简单的问题
# 我们看下以前的我们会怎么搞
assume cs:codesg
codesg segment 
mov ax,0h
mov cx,3h
multiA:  add ax,1h
       push ax 
	   loop multiA 
mov cx,3h
mov ax,0h
multiB:  pop bx 
      add ax,bx
	  loop multiB
mov ax,4c00H
int 21H
codesg ends 
end

这里我们利用栈空间为我们存储1,2,3三个元素,然后依次弹栈进行计算,但是有的小伙伴肯定觉得这么写很墨迹,而且可读性也不高。于是我们又想起了之前在DOSBOX中曾经讲过的E指令:
在这里插入图片描述

在dosbox中我们可以很灵活的通过E指令来分配内存地址,当然,E指令也有它自身的问题:它需要我们为他指定一段内存地址,而这段内存地址需要我们确保没有被其他指令段引用,或者说我们需要为E指令担保,这段内存是安全的。 但是显然,我们在日常开发中很难将精力分散到每一个指令的内存管理,那么我们有没有其它方法可以解决这个问题呢?

2. 操作系统与内存

我们首先回顾一下程序执行的过程:

  1. 编译
    由编译程序将用户源代码编译成若干个目标模块。
  2. 连接
    将刚刚编译后的模块和所需要的库函数连接在一起,形成一个完整的可执行模块。
  3. 装入
    由装入程序将装入模块装入内存运行。

什么是装入程序呢?在这个阶段我们可以简单的理解为就是我们的操作系统。操作系统会在程序装入的时候为他分配一段安全的内存,这一片内存不会被其他进程干扰,是相对安全且不需要我们去关注的。

3. dw指令与数据段

汇编指令中有一个伪指令:DW指令,它可以定义十六位的数据,每个数据需要两个内存单元存放,可以将数据放入安全的内存空间中。通常来说,DW指令会将数据存放到CS:0开始的区域。我们来简单的写一个DEMO看下效果:

assume cs:codesg
codesg segment 
dw 1H,2H,3H,4H,5H,6H,7H,8H

mov bx,0H 
mov ax,0H
mov cx,8H
addAll: add ax,cs:[bx]
        add bx,2H
		loop addAll 

mov ax,4c00H
int 21H
codesg ends 
end

运行结果:
在这里插入图片描述

4. start指令

细心观察的小伙伴已经发现了一个问题:
在这里插入图片描述
编译器似乎并不能按照我们预期的顺序开始执行程序,换句话说仿佛编译器并不知道程序的入口在哪里。这个时候我们就需要用一个新的命令:start 来为程序指定一个程序入口。

# 我们来改造一下程序
assume cs:codesg
codesg segment 
dw 1H,2H,3H,4H,5H,6H,7H,8H

start :mov bx,0H 
mov ax,0H
mov cx,8H
addAll: add ax,cs:[bx]
        add bx,2H
		loop addAll 

mov ax,4c00H
int 21H
codesg ends 
end start 
end

我们来看下指令顺序,已经符合我们的预期了。
在这里插入图片描述

二、内存与栈空间

当我们学会了如何为数据段分配安全的内存空间,那么我们又该如何为数据栈分配安全的空间呢?
思路:

  1. 我们之前学会了为数据段分配内存,每一个数据段会获得2个内存单元
  2. 栈空间的本质也是为了存储数据
  3. 我们可以用空数据占位,然后将对应的内存分配给数据栈

代码实现

assume cs:codesg
codesg segment 
dw 1h,2h,3h,4h,5h,6h,7h,8h
dw 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h

start :
MOV AX,CS
MOV SS,AX
MOV SP,30h ;
MOV AX,0H
MOV CX,8h
PUSHDATA:  add ax,1h
           push ax 
		   loop PUSHDATA

mov ax,4c00H
int 21H
codesg ends 
end start 
end

三、多数据段

在前面的内容中,我们在程序中用到了数据和栈,将数据和栈和代码都放到了一个段里,但是这样我们在编程时需要格外注意什么是数据,什么是栈,什么是代码,这么做显然让程序显得混乱,而且在数据更多的情况下会受到限制。所以我们接下来考虑的应该是如何通过多个段来存放数据,代码和栈。还记得我们之前讲过的assume关键字吗?sssume可以将某个段寄存器和一个段相互关联,那是不是我们只要关联多个段就可以分清代码,数据和栈?让我们来试一下:

assume cs:code,ds:data,ss:stack

data segment
dw 1h,2h,3h,4h,5h,6h,7h,8h
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 ax,data
		mov ds,ax
		mov bx,0
		mov cx,8
mov ax,4c00H
int 21H
code ends 
end start

end

观察结果
在这里插入图片描述
我们观察到我们可以直接将数据段赋予段寄存器以达到使用的目的,这里需要注意的是声明段的顺序很重要,当前代码中不能够使用还未被声明的段。

结语

今天的内容就到此结束了,有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。
屏幕前努力学习的你如果想要持续了解博主最新的学习笔记或收集到的资源,可以关注博主的个人公众号。这里有很多最新的技术领域PDF电子书及好用的软件分享在这里插入图片描述

码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
如果大家有什么意见和建议请评论区留言或私聊博主,博主会第一时间反馈的哦。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓龙oba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值