练习1:
1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 4 data ends 5 6 stack segment 7 dw 0, 0, 0, 0, 0, 0, 0, 0 8 stack ends 9 10 code segment 11 start: mov ax,stack 12 mov ss, ax 13 mov sp,16 14 15 mov ax, data 16 mov ds, ax 17 18 push ds:[0] 19 push ds:[2] 20 pop ds:[2] 21 pop ds:[0] 22 23 mov ax,4c00h 24 int 21h 25 26 code ends 27 end start
用r指令查看stack段地址076B,由于stack内是8字即16个字节。所以data区短地址是076A,刚好数据区也是16个字节,用d 076A:0 F查看数据元素。
用u指令反汇编代码,得到代码段最后是076A:001D。用g命令执行该代码。
可以得到CS=076C,SS=076B,DS=076A。假设CODE段的段地址为X,则DATA段的段地址为 X-2 ,STACK段的段地址为 X-1 。
练习2:
1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h 4 data ends 5 6 stack segment 7 dw 0, 0 8 stack ends 9 10 code segment 11 start: mov ax,stack 12 mov ss, ax 13 mov sp,16 14 15 mov ax, data 16 mov ds, ax 17 18 push ds:[0] 19 push ds:[2] 20 pop ds:[2] 21 pop ds:[0] 22 23 mov ax,4c00h 24 int 21h 25 26 code ends 27 end start
用d查看076A:0 F可知data数据区在076A:0 3
发现此处数据区没有变化,CS=076C,SS=076B,DS=076A。假设CODE段的段地址为X,则DATA段的段地址为 X-2 ,STACK段的段地址为 X-1 。
同第一题结果一样。但此处的栈空间和数据区间都没有达到8个字即16个字节。那么段中数据占N个字节,则程序加载后,该段实际占有的空间为 (N/16+1)*16 。
当N被16整除时: 占有的空间为(N/16)*16
当N不被16整除时: 占有的空间为(N/16+1)*16,N/16取最小正整数,还有一个余数,余数肯定小于16,加上一个1,再乘16字节。
程序加载后分配空间是以16个字节为单位的,也就是说如果不足16个字节的也分配16个字节。
练习3:
1 assume cs:code, ds:data, ss:stack 2 code segment 3 start: mov ax,stack 4 mov ss, ax 5 mov sp,16 6 mov ax, data 7 mov ds, ax 8 push ds:[0] 9 push ds:[2] 10 pop ds:[2] 11 pop ds:[0] 12 mov ax,4c00h 13 int 21h 14 code ends 15 data segment 16 dw 0123h, 0456h 17 data ends 18 stack segment 19 dw 0,0 20 stack ends 21 end start
由此可知stack的段地址即SS=076E,data的段地址为076D,代码段的段地址CS=076A。
数据data区没有改变,原数据详细地代码请展开练习3 下面的代码。
假设CODE段的段地址为X,则DATA段的段地址为 X+3 ,STACK段的段地址为 X+4 。
练习4:
将1、2、3中最后最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),会怎么样?
实验证明,只有第三个程序,是能够正常运行。
如果不指明入口位置,则程序从所分配的空间开始执行。只有第三个是以代码段开始,则不会将其他数据段当成代码段执行。
练习5:
编写code段中代码,将a段和b段中的数据依次相加,将结果存到C段中。
1 assume cs:code 2 a segment 3 db 1,2,3,4,5,6,7,8 4 a ends 5 6 b segment 7 db 1,2,3,4,5,6,7,8 8 b ends 9 c segment 10 db 8 dup(0) 11 c ends 12 code segment 13 start: 14 mov ax,a 15 mov ds,ax 16 mov ax,b 17 mov es,ax 18 mov ax,c 19 mov ss,ax 20 mov bx,0 21 mov cx,8 22 z: mov al,[bx] 23 add al,es:[bx] 24 add ss:[bx],al 25 inc bx 26 loop z 27 mov ax,4c00h 28 int 21h 29 code ends 30 end start
实现功能。
练习6:
编写code段中代码,用PUSH指令将A段中的前8个字型数据,逆序存储到B段中。
1 assume cs:code 2 a segment 3 dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh 4 a ends 5 6 b segment 7 dw 8 dup(0) 8 b ends 9 10 code segment 11 start: 12 mov ax,a 13 mov ds,ax 14 mov ax,b 15 mov ss,ax 16 mov sp,10H 17 mov bx,0 18 mov cx,8 19 z:push [bx] 20 add bx,2 21 loop z 22 mov ax,4c00h 23 int 21h 24 code ends 25 end start
实验成功。
实验总结与感受:
这个章节内容很少,确实很少,但实验不少。本章主要是综合运用前面的内容,定义栈,使用段地址加偏移地址,进行访问,存储等等。
程序一步步走向成熟,代码越来越多,期待编写自己第一个不用在debug中调试才能看见效果的有意义的程序。