您的位置:首页 > 其它

汇编语言入门:一段安全的段空间

2018-02-15 10:31 197 查看
要知道,内存空间时不能随意随意读写的,因为可能会触及操作系统内存,这就是“不安全”的做法,是一次不合法的行为

补充:段前缀

在这之前,先说另一个知识点:

段前缀:我们可以通过“段前缀”指令来认为更改默认的段寄存器

例如:
mov AX, [0]
mov AX, DS:[0]
是等价的(默认为DS)


我们可以这样显式的指定我们要的段地址:

mov AX, ES:[0]
:段地址在ES中,偏移地址为0


对于8086CPU,段地址寄存器有DS、CS、ES、SS

一段安全的段空间

永远记住,我们是在操作系统的环境中工作,操作系统管理所有的资源,当然也包括内存,如果我们需要向内存空间写入数据的话,要使用操作系统给我们分配的空间,而不应直接使用任意指定的内存单元向里面写数据

同样记住,我在学习汇编语言,要使用它来获得底层的编程体验,理解计算机底层的基本工作原理,所以我们要尽量直接对硬件编程而不去理会操作系统

在纯DOS(实模式)下,可以不理会DOS而直接使用汇编语言去操作真实的硬件,因为运行在CPU实模式下的ODS没有能力对硬件系统进行全面、严格地管理;但是在Windows 2000、Unix这些运行于CPU保护模式下的操作系统中,是无法忽视操作系统的存在的,硬件已经被这些操作系统利用CPU保护模式所提供的功能全面而严格地管理了

一段安全的空间:在一般的PC机中,DOS方式下,DOS和其它合法的程序一般都不会使用
0:200~0:2ff
256
个字节空间,所以这段空间是安全的


(至于为啥这256个字节空间是安全的,以后再讲~)

So……以后当我们需要直接向一段内存中写入一段内容时,就使用
00200H~002FFH
这段空间




(看图,debug模式下0:200内存确实没有数据……)

段前缀的使用

举个栗子如何:^ - ^

谜面:请将内存fff:0~fff:b单元中的数据拷贝到0:200~0:20b单元中(汇编实现)

分析:将目标地址0:200~0:20b看成0020:0~0020:b,和源地址单元的偏移地址从同一数值开始(减少寄存器的使用)

谜底:

assume CS:code
code segment
mov BX, 0      ;(BX)=0偏移地址从0开始
mov CX, 12     ;(CX)=12,循环12次
s:mov AX, 0FFFH  ;为DS赋值做准备
mov DS, AX     ;(DS)=0FFFH,准备从“源段”读取数据
mov DL, [BX]   ;(DL)=((DS)*16+(BX)),将FFFF:BX中的数据送入DL
mov AX, 0020H  ;为DS赋值做准备
mov DS, AX     ;(DS)=0020H,准备向“目标段”传送数据
mov [BX], DL   ;((DS)*16+(BX))=(DL),将源数据送入目标单元
inc BX         ;(BX)=(BX)+1
loop s

mov AX, 4C00H
int 21H
code ends
end


上面因为源单元FFFF:X和目标单元0020:X相距大于64K(一个段的最大长度)所以每次循环要用两次即设置两次DS的值(现从源地址获取数据,再往目标地址写入数据)

BUT!上面的做法效率不高,可以使用不同的段地址寄存器!

改进版的谜底:

assume CS: code
code segment
mov AX, 0FFFFH    ;看吧
mov DS, AX        ;这四行
mov AX, 0020H     ;分别使用两个不同的段寄存器
mov ES, AX        ;DS和ES(转下)
mov BX, 0
mov CX, 12
s:mov DL, [BX]      ;于是每次循环
mov ES:[BX], DL   ;显示的指定前缀(因为不是默认的DS)
inc BX
loop s            ;只需要改变偏移地址(BX),而不需要改变段地址的值了

mov AX, 4C00H
int 21H
code ends
end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  汇编语言 DS ES