1、在代码段中使用数据
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即“define word”,使用dw定义了8个字型数据。这8个数据是在代码段的偏移0、2、4、6、8、A、C、E、处。程序运行时,它们的地址就是CS:0, CS:2,CS:4,CS:6,CS:8,CS:A,CS:C,CS:E。
也就是说从CS:10H开始才是汇编指令对应的机器码。所以这里就需要使用标号start来指出程序的开始和结束。
2、在代码段中使用栈
完成下面的程序,利用栈,将程序中定义的数据逆序对存放。 assume cs:codesg codesg segment dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;16个字单元用作栈空间 start:
mov ax,cs
mov ss,ax mov sp,30h
mov bx,0 mov cx,8 s:
push cs:[bx]
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
3、将数据、代码、栈放入不同的段
assume cs:code,ds:data,ss:stacksg data segment dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h data ends stacksg segment stack ;这里需要在segment后面加上stack,否则debug时寄存器里面的数据不对 dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 stacksg ends code segment start: mov ax,stacksg mov ss,ax mov sp,20h mov ax,data mov ds,ax mov bx,0 mov cx,8 s: push [bx] add bx,2 loop s mov bx,0 mov cx,8 s0: pop [bx] add bx,2 loop s0 mov ax,4c00h int 21h code ends end start
在程序中,段名就相当于一个标号,它代表了段地址。例如上面程序中的data就是数据段的段地址,是一个常量值。
所以mov ds,data这种写法是错误的。8086CPU不允许将一个数值直接送入段寄存器。
我们在程序中用伪指令"assume cs:code,ds:data,ss:stacksg"将cs、ds和ss分别和code、data、stacksg段相连。
我们在源程序的最后用"end start"说明了程序的入口,这个入口将被写入可执行文件的描述信息,可执行文件的程序被加载入内存后,CPU的CS:IP被设置指向这个入口,从而开始执行程序中的第一条指令。
由于我们在程序中设置ss指向stack,设置ss:sp指向stack:20,CPU执行这些指令后,将把stack段当作栈空间使用。
CPU若要访问data段中的数据,则可使用ds指向data段,用其他的寄存器(如bx)来存放data段中的数据的偏移地址。
总之,CPU到底如何处理我们定义的段中的内容,是当作指令执行,当作数据访问,还是当作栈空间,完全是靠程序中具体的汇编指令,和汇编指令对CS:IP,SS:SP,DS等寄存器的设置来决定的。
上述程序中的data、stack标号可以使用任意的合法字符,只是data、stacksg在我们读程序的时候更加方便而已。