本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
学习教材:《汇编语言(第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,data再mov ds,ax
首行assume将cs、ds、ss和对应的段相连,但是CPU并不知道它们,因此后面还要修改cs、ds、ss来指向对应的段
注意活用三大段寄存器:cs、ds、ss
后记
- dw定义字型数据,又可以开辟空间
- 添加标号搭配end改变入口
- 程序分段便于理解
- 定义栈注意栈顶指针
- 别忘了对三大段寄存器的初始化