数据段的学习
我们在一开始在debug中是使用a命令来进行编写代码的,这样是不安全的,我们使用a命令可以在任意的位置编写代码,然后使cs:ip指向这个地址,便可以执行我们所写的代码了,然后我们又是创建一个asm类型的文件,我们称之为源文件,然后通过编译和链接后生成exe的文件,然后在debug中进行运行的,使用这种方式运行的好处是,我们的内存空间时系统分配给程序的,是安全的。
可以使用dw来定义字类型的数据 将数据放在代码段里面
eg: dw 0123H,43H
在代码段中的某条指令之前添加start伪指令可以指示指令的执行位置,因此我们可以在代码段内定义数据,这时cs:ip是指向我们定义的数据,因此这个时候便可以使用start伪指令来使cs:ip指向我们的第一句代码。
在代码段中定义数据后,系统会分配空间,我们可以将这段空间当做栈来使用,只需要设置ss:sp即可
在代码内定义数据当做栈来使用
assume cs:code
code segment
dw 1,2,3,4,5,6,7,8
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
start: mov ax,cs
mov ss,ax
mov sp,0H
mov bx,10H
mov cx,8
num:pop ss:[bx]
inc bx
inc bx
loop num
code ends
end start
assume cs:code
code segment
;覆盖这些数据的内容
dw 1,2,3,4,5,6,7,8
start: mov cx,8
mov bx,0
mov ax,cs
mov ds,ax
mov ax,0
num:mov ds:[bx],ax
add bx,2
loop num
code ends
end start
上面我们将数据放在了代码段,因此开始时我们的ip指针不会指向0,因此这样看起来混乱
start伪指令表达了程序的入口
下面这个例子是使用在代码段里面定义定义数据和栈空间
assume cs:code
code segment
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 1,2,3,4,5,6,7,8
start: mov ax,0
mov bx,8
mov cx,0
code ends
end start
观察每个寄存器的值
可以看到ip的值为0030,并不是从0开始的,这表示我们的代码段的开始偏移地址为30,我们知道代码段的寻址范围应该是0~FFFFH,但是有一段空间已经被占用了。
下面显示的是代码段的值
可以看到0000H~0020H是我们定义的栈的内容,0020H到0030H是数据的内容,在0030H以后的内容才是我们的代码。
通常使用这样的方式定义代码段数据段和栈段
assume cs:code,ds:data,ss:stack
;上面这个伪指令的意思便是说明,这里怎么翻译,哪里怎么翻译
data segment
dw 1,2,3,4,5,6,7,8
data ends
stack segment
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start: mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,20H
mov ax,0
mov bx,8
mov cx,0
code ends
end start
上面这个源程序将数据段,代码段和栈段分开进行了定义,然后使用下面几条指令对ss和ds寄存器进行了赋值。
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,20H
下面是我们运行这几条指令后的结果
开始时寄存器的值
运行这几条指令后寄存器的值
观察这几个段寄存器,ss和ds发生了改变,这是我们前面赋值的结果。
代码段
数据段
栈段
每个寄存器的值
可以看到每个段都是从 段寄存器:0开始,偏移地址的开始都是0,其实数据栈和代码在内存中的位置并没有变,只是表达地址的方式变了,内存是使用 段地址*10H+偏移地址=物理地址 来确定的,我们想要数据段,代码段和栈段的偏移地址从0开始,只需要设置段地址便可以。
比如:
1000H:200H
1020H:0H
这两个表示的都是10200H地址