正在加载……
专注、离线、切勿分心
◆ 在一个段中存放数据、代码、栈;
◆ 将数据、代码、栈放入不同的段中;

在代码段中使用数据
assume cs:code
code segment
     dw 0123h , 0456h , 0789h , 0abch , 0defh , 0fedh , 0cbah , 0987h         ; 代码段中的数据
start:     mov bx , 0
              mov ax , 0
              mov cx , 8
s:           add ax , cs:[bx]
              add bx , 2
              loop s 
              mov ax , 4c00h
              int 21h
code ends
end  start
dw: 定义字型数据。这里定义了8个字型数据,一共占 16 字节

因为程序段定义在代码段中,程序运行的时候 CS 中存放代码段地址,数据定义处于代码段的最开始,所以偏移地址为 0 ,8个数据在代码段的偏移 0,2,4,6,8,A,C,E处。
递增的偏移地址用 bx+2 来存放。

程序编译链接后,用 debug -u  命令查看,最开始的16位中存放的不是汇编指令,而是 dw 定义的数据;如果想程序从第一条汇编指令开始执行,可以用伪指令 start    标号
//如果不加start,刚进debug调试不是我们写的代码的第一条指令,而是在执行命令存放我们定义的数据。

end 伪指令不仅通知编译器程序结束外,还可以通知编译器程序的入口,现在指明入口在 start 处
        
// 不加start,        \\ 这里是一样的



在代码段中使用栈 
; 定义8个字型数据,把它们依次数据入栈,然后再依次出栈到这8个字单元中
; 首先要定义一段可用的栈空间,这段空间要由系统来分配
assume   cs:codesg
codesg   segment
              dw   0123h , 0456h , 0789h , 0abch , 0defh , 0fedh , 0cbah , 0987h  
              dw   0 , 0 , 0 , 0 , 0 , 0 , 0 , 0                    ; 用dw定义8个字型数据,程序加载后取得这8个字的内存空间,存放这8个数据。后面的程序中将这段空间当作栈来使用,这段区间被放到其他地方了,后面debug看内存只能看到前面的数据。
start:     mov ax , cs
              mov ss , ax
              mov sp , 32              ; 设置栈顶,32正好是定义数据段的最后一个31的下一位,表示空栈
              mov bx , 0
              mov cx , 8
s:            push cs:[bx]       ; cs:0 和 cs:1 就是0123h
              add bx , 2
              loop s                       ; 循环将最开始8个数据放入栈
              mov bx , 0  
              mov cx , 8
s0:         pop cs:[bx]
              add bx , 2
              loop s0                   ; 循环将栈中数据放回 0~16单元中
              mov ax , 4c00h
              int 21h
codesg ends
end start
   CS:IP==076A:0020   设置好栈偏移后 SS:SP==076A:0020;数据都是放在栈中保存,栈向下生长,低位数据放在高位



将数据、代码、栈放入不同的段
  将数据、代码、栈放入同一个段会使程序显得混乱,而却一个段的容量不能超过 64KB(8086cpu16位数据线,只能寻址最大2^16位,一个偏移最大ffff,表示空间16*16*16*16也是64KB)
;改写上面的程序:
assume   cs:codesg , ds:data , ss:stack
data   segment
              dw   0123h , 0456h , 0789h , 0abch , 0defh , 0fedh , 0cbah , 0987h  
data   ends
stack  segment
              dw   0 , 0 , 0 , 0 , 0 , 0 , 0 , 0     
stack  ends
codesg  segment              
start:     mov ax , stack         ; 段名就代表段地址
              mov ss , ax
              mov sp , 16             ; 这里不用算上data的空间,偏移16就可以         
              mov ax , data
              mov ds , ax             ; ds指向data段,不是代码段开头了,是专门的数据段,所以要从指定
              mov bx , 0
              mov cx , 8
;  s:            push cs:[bx]     ; 这里出错了,这个时候cs已经偏移到076c,数据段还是在076A的地方
s:            push data:[bx]               ; 这个时候data已经关联了数据段
              add bx , 2
              loop s                     
              mov bx , 0 
              mov cx , 8
s0:         pop cs:[bx]
              add bx , 2
              loop s0                  
              mov ax , 4c00h
              int 21h
codesg ends
end start
程序中的伪指令是由编译器执行的,真正CPU执行的只是汇编指令,我们这样书写只是便于代码阅读,CPU执行的时候根据ends start找到入口,这样CPU就将code段中的内容当做指令来执行了。我们设置了ds指向data段,用bx来存放偏移,这样cpu就按我们预想的把我们定义的数据当做数据段了。

CPU处理我们定义的段中内容,完全是靠程序中具体的汇编指令,和汇编指令对 CS:IP、SS:SP、DS等寄存器的设置来决定的。


data==076A
stack==076B
CS==076C
CS:IP==076C:0








posted on 2017-09-18 23:55  正在加载……  阅读(286)  评论(0编辑  收藏  举报