◆ 在一个段中存放数据、代码、栈;
◆ 将数据、代码、栈放入不同的段中;
在代码段中使用数据
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 |