刚刚学markdown,为适应语法,下面的格式包含 “ 炫技 ” 成分,
看着难受也不关我事。
文章目录
包含多个段的程序
dw:数据存放在哪里
程序需要其他空间来存放数据,这个内存空间一定要是安全的。而在操作系统允许的情况下,程序可以取得任意容量的空间。
而程序取得所需空间的方法有两种:
- 加载程序时系统自动分配内存空间
- 执行过程中向系统申请内存空间
申请方法不讨论,我们下面讨论能让系统心甘情愿为我们分配空间的方法。
这种方法的关键是定义段
assume cs:code
code segment
dw 0123h,0456h,0789h
==dw(define word)==是定义字型数据[^1]的关键字
注意:dw定义的数据内存空间处于代码段的最开始,
所以它的偏移地址 CS:0,CS:2 …
由于dw在代码指令之前,所以要借助start关键字来指定程序入口所在。
dw 0123h ...
start: mov bx,0
mov ax,0
...
code ends //结束代码段
end start
程序之所以知道哪一条是第一个要执行的指令,是因为 可执行文件中的描述信息 的指明。而一个可执行文件由描述信息和程序本身 组成,
- 程序来自于源程序中的汇编指令和定义数据;
- 描述信息主要是编译和连接过程中,对源程序的伪指令进行处理得到的信息。
实际上,伪指令end 和 紧随其后的标号 就会被转化为地址存放在描述信息中。
如果你的指令操作有内存空间的需求(像需要一些memory space来作为栈),
可以用数据0 提前占位。
dw 0123h,0456h,0789h #该数据段在最开始 CS:0处,即CS :00~CS:06
dw 0 0 0 0 0 0 0 0 #预先占位的内存,地址为CS:07~CS:26
由上,dw的作用可以说有两个方面
- 定义数据
- 开辟内存空间
定义多个段
场景
值得注意的是,代码段和数据段、栈等在源程序中要分段处理。定义多个段,不仅能让代码更简洁,还因为一个段本身的容量限制。应考虑定义多个段来存放不同内容。
格式
assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h
data endsstack segment
dw 0,0,0,0,0
stack ends
code segment
start: mov ax,stack
mov sp,2h
mov ax,data
code ends
end start
规律:
- 定义不同的段时,要有不同的段名
- 段名相当于一个标号,它代表了段地址。
该段中数据的段地址由段名代表,偏移地址看他在段中的位置
(这里强调一下,不允许将数值直接送入段寄存器)
当我们谈到多个段时,我们谈些什么
①segment 与 ends 是配套使用的,而段名则是随意命名。编译器不管你是stack,stock乃至st0ck,在它眼里只是一个段。我们定义段为code,stack,data等仅仅为了方便用户阅读。
②assume cs:code 等伪指令是由编译器执行,跟CPU没什么关系,也不会将CS真的指向code。具体的意义这里不深究。
[^1]:这些定义的数据内存大小当然是16字节喽
灵活定位内存地址
何谈灵活
先明确一下,所谓的灵活定位,只是因为加了一个变量:idata和两个类bx寄存器 si和di。
- idata是任意常量
- 同bx一样,bp是另一个基址寄存器
- si和di是类似bx功能的变址寄存器(只是这俩不能分成两个8位寄存器使用)
所以指定内存地址,现在的方法有:
[bx(+idata)] [si(+idata)] [di(+idata)]
[bx+si(+idata)] [bx+di+idata]
注意点:
- [bx+si]可以表示为[bx][si]
- si和bi两个变址寄存器不能同时使用。
bx和bp两个基址寄存器不能同时使用
AND OR的介绍
AND
格式:AND 数据寄存器 对应进制数据
效果:逻辑意义上的按位与
应用:可通过特定数据将对象数据的相应位设为0,其他位不变
例子:mov al,00111011B
OR
相应AND,不解释。
应用:将对象数据的相应位设为1,其他位不变。
字符形式的数据
格式:
db
data segment
db 'unIX'
db ‘LeBron’
data ends
存储方式为ASCII码
地址偏移同dw
一个规律:ASCII码中字母的二进制形式,第五位为0即大写,1即小写。
ASCII码
文本编辑过程中,:
1.(键盘等)文本信息输入
2.信息转为ASCII码存在指定内存
3.文本编辑器将内存中的ASCII码信息送到显卡 显存中
4.显卡用ASCII码规则解释传入信息
5.数据信息转为字符,并由显卡驱动显示器,显示在屏幕上
[id]: https://baike.baidu.com/item/ASCII/309296?fromtitle=ascii%E7%A0%81&fromid=99077&fr=aladdin
关于数据处理的两点
数据处理有两个核心问题:
- 处理数据在什么地方
- 处理数据有多长
(这里给出描述性符号:reg指代其他寄存器,sreg指代段寄存器)
机器指令处理数据,不关心数据的值,只关心指令执行前,将要处理数据的位置。
数据位置
汇编指令 | 指令执行前的数据位置 |
---|---|
mov bx,[0] | 内存,ds:0 单元 |
mov bx,ax | CPU内部,ax寄存器 |
mov bx,1 | CPU内部,指令缓冲器 |
由表可知有三种位置表达:立即数,寄存器,EA+SA(段/偏移地址)
寻址方式
直接寻址 - 立即数
立即数
上面的1称为立即数(idata)
直接包含在机器指令中,在汇编指令中直接给出。
间接寻址 - 数据寄存器
[ax] , [bx]
相对寻址 - 基址寄存器 + 立即数
- 用于结构体:[bx].idata
- 用于数组:idata[si],idata[di]
- 用于二维数组:[bxi][data]
基址变址寻址 - 基址寄存器 + 变址寄存器
二维数组 :[bx][si]
相对基址变址寻址 - 基 + 变 + idata
二维数组:idata[bx][si]
结构中的数组 [bx].idata[si]
数据长度
我们学习的8086cpu只有两种尺寸数据处理:byte和word。
通过以下方式处理数据长度
1.寄存器名
2.没有寄存器名,利用操作符 X ptr 指明长度
mov word ptr ds:[0],1
mov byte ptr ds:[0],1
3.指令默认
push[1000h]:push指令只进行字操作。
END
last but not least:
当我们谈论自由,我们谈论什么
当我们谈论爱情,我们谈论什么
[当我们谈论跑步,我们谈论什么](###直接寻址 - 立即数)