学汇编,记笔记(五)《汇编语言》王爽著——程序分段_使用数据和栈_定义汇编程序的入口

450 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著

程序获取空间

加载程序时候可以预先获取到空间,只需要在源程序中提前声明

可以想象成C语言的define 123宏定义

章末实验

一、在代码段中使用数据

例如:累加1,4,7,9。之前是一个个的加到ax寄存器中,我们现在想使用循环来完成,就可以在程序中定义我们希望处理的数据,当成为可执行文件执行时,它们就会加载到内存中,获得了存储空间

dw n代码用于定义字型数据,即define word,每个长2B,通过这个代码将需要处理的数据加载到内存中

assume cs:df_add
df_add segment
	dw 1,4,7,9
	
	mov ax,0
	mov bx,0
	mov cx,4
	
	s:add ax,cs:[bx]
	add bx,2  ;字型数据,因此偏移2B
	loop s
	
	mov ax,4c00h
	int 21h
	
df_add ends
end

在Debug中调试:

在这里插入图片描述 首行代码并不是我们希望执行的代码,希望运行的代码在7~B之间

使用d cs:0查看字节内容

在这里插入图片描述 程序最前面是我们定义的数据1,4,7,9

至于为什么这里是01000400,请查看之前的笔记,因为数据在CPU内是反着存储的!高位部分存入高位地址,因此正常是00010004

这里就可以明白了:首先dw定义的字型数据被加载到了程序最前面,因此出现了奇怪的首行代码,而这段是数据,不是我们想执行的代码,因此需要修改入口函数

二、定义程序的入口

假如程序的默认入口不是我们希望执行的数据就需要更改入口。更改入口的目的就是为了要让CPU明白和区分数据还是代码,否则将会把数据当作代码运行

在end后添加标号即可定义入口,end会告知CPU当前程序的入口和结束

assume cs:df_add
df_add segment
	dw 1,4,7,9
	
	start:mov ax,0 ;入口
	mov bx,0
	mov cx,4
	
	s:add ax,cs:[bx]
	add bx,2
	loop s
	
	mov ax,4c00h
	int 21h
	
df_add ends
end start ;定义入口

这里的start仅仅是一个标号,就像循环标号s一样可以写成其他,比如main等等

现在程序的入口就修改到了我们希望的代码行,CS:IP变成了此时的0B3E:0008

在这里插入图片描述

三、在代码中使用栈

从上面可以看出,定义的字型数据以线性的方式存入程序最前面,就可以通过这个方式为一个空栈获取空间

下面是定义栈并且依次入栈的代码:

assume cs:get_stack
get_stack segment
	dw 1,4,7,9 
	dw 0,0,0,0,0,0 ;用来作为栈空间,空栈
	
	start:mov ax,cs
	mov ss,ax
	mov sp,14h ;将栈顶指向最高位的0的下一个位置,14h是两次定义的10个字的总长度
	
	mov bx,0
	mov cx,4
	
	s:push cs:[bx] ;依次入栈
	add bx,2
	loop s
	
	mov ax,4c00h
	int 21h
	
get_stack ends
end start

栈顶是最高位的0的下一个位置,有疑问请查看之前的笔记,因此偏移量是14h,修改sp指向它,即可完成一个栈的空间开辟和定义

“所以我们在描述dw的作用时,可以说用它定义数据,也可以说用它开辟内存空间。”

四、程序分段

将程序划分成数据段、栈段和代码段,一是方便理解,二是假设三者之和占用了超过上限的64KB空间,就不能放在一个段中

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

data segment ;数据段
	dw 1,4,7,9
data ends

stack segment ;栈段
	dw 0,0,0,0,0,0
stack ends

code segment ;代码段
	start:mov ax,stack
	mov ss,ax
	mov sp,14h ;引用栈段地址,定义了一个空栈
	
	mov ax,data 
	mov ds,ax ;引用数据段地址
	
	mov bx,0	
	mov cx,4
	
	s:push [bx] ;自动去ss寻址
	add bx,2
	loop s
	
	mov ax,4c00h
	int 21h
code ends

end start

各个段名只是标号,可以任意取

注意:在引用段地址时不可以直接传入段寄存器,它本质上还是一串数据,需要普通寄存器ax来辅助传入,因此先mov ax,datamov ds,ax

首行assume将cs、ds、ss和对应的段相连,但是CPU并不知道它们,因此后面还要修改cs、ds、ss来指向对应的段

注意活用三大段寄存器:cs、ds、ss

后记

  • dw定义字型数据,又可以开辟空间
  • 添加标号搭配end改变入口
  • 程序分段便于理解
  • 定义栈注意栈顶指针
  • 别忘了对三大段寄存器的初始化