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

要知道,内存空间时不能随意随意读写的,因为可能会触及操作系统内存,这就是“不安全”的做法,是一次不合法的行为


补充:段前缀

在这之前,先说另一个知识点:
段前缀:我们可以通过“段前缀”指令来认为更改默认的段寄存器
例如: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:2ff256个字节空间,所以这段空间是安全的
(至于为啥这256个字节空间是安全的,以后再讲~)

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

汇编语言入门:一段安全的段空间_第1张图片
(看图,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

你可能感兴趣的:(汇编语言)