汇编语言(王爽第三版) 实验5编写、调试具体多个段的程序
(2017-04-22 14:58:13)
标签:
汇编王爽it教育 |
分类: 汇编语言(王爽第三版)实验 |
实验5 编写、调试具体多个段的程序
一。将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
assume
cs:code,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 code
segment start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax,4c00h
int 21h code ends
end start
程序分析:由于是初次接触,我们逐步讲解,废话多点。
(1)此程序考察的是内存中数据段和栈段的定义。
E:\assembly>debug eee.exe
-r
AX=0000
DS=0B55
0B67:0000
B8660B
程序分析:我们什么也没执行,此时我们在data段定义的数据在哪?在ds:0100H处(原来讲过,程序最开始时ds:00~ds:100H是留给程序与操作系统通讯使用的psp内存段,参见书中p92);也就是说我们在ds:100H、0B55:100H或0B65:00处可以看见这些定义的数据。见下图。
-d ds:100
0B55:0100
0B55:0110
(2)mov ax,stack
-d ss:0
0B66:0000
0B66:0000
完全等价于:
0B55:0110
(3)
(4)
-d ss:0
0B66:0000
-d ss:0
0B66:0000
(5)pop ds:[2]
-d ds:0
0B65:0000
其实在内存第3、4字节中是pop弹栈回写的数据。实际是没有变化,但是经过了pop的回写的。
总结:观察栈的结构,注意执行push和pop指令的汇编层面含义和CPU执行的步骤。进一步理解内存的直接寻址方式。返回前,各寄存器状态如下:
AX=0B65
DS=0B65
0B67:001D
B8004C
答案:
①CPU执行程序,程序返回前,data段中的数据
②CPU执行程序,程序返回前,CS=0B67,SS=0B66,DS=0B65
③设程序加载后,CODE段的段地址为X,则DATA段的段地址为
二。将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h data ends
stack segment
dw 0,0 stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax,4c00h
int 21h code ends
end start
程序分析:(不再详细分析了)
-d ds:100
0B55:0100
0B55:0110
-t
AX=0B65
DS=0B65
0B67:001D
B8004C
答案:
(1)CPU执行程序,程序返回前,data段中的数据为多少?
(2)CPU执行程序,程序返回前,CS=0B67, SS=0B66, DS=0B65.
(3)程序加载后,code段地址设为X,则data段地址为(x-2),stack段的段地址为(X-1).
(4)对于如下定义的段:
name segment
name ends
三。将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
assume cs:code,ds:data,ss:stack
code segment
start:
code ends
data segment
data ends
stack segment
stack ends
end start
程序分析:
-r
AX=0B68
DS=0B68
0B65:001D
B8004C
答案:
(1)CPU执行程序,程序返回前,data段中的数据为多少?
(2)CPU执行程序,程序返回前,CS=0B65, SS=0B69, DS=0B68.
(3)程序加载后,code段地址设为X,则data段地址为(x+3),stack段的段地址为(X+4).
0B65:0000
0B65:0010
0B65:0020
0B65:0030
0B65:0040
四。
五。编写code段中的代码,将a段和b段数据依次相加,结果存入c段
assume cs:code
a segment
a ends
b segment
b ends
c segment
c ends
code segment
start:
code ends
end start
程序分析:
assume cs:code
a segment
db 1,2,3,4,5,6,7,8 a ends
b segment
db 1,2,3,4,5,6,7,8 b ends
cz segment
db 0,0,0,0,0,0,0,0 cz ends
code segment
start:
mov ax,a
指向a段 mov ds,ax ;ds
mov ax,b
指向b段 mov es,ax ;es
mov bx,0
mov cx,8 计算8次,故计数器为8 ; s:
mov dl, [bx] ;将ds:[bx]内存单元按字节送入dl,此循环用到ax
将ds:[bx]与es:[bx]内存单元值相加 add dl, es:[bx] ;
保护ds值,因为下面用到ds了 push ds ;
我的编译器不认C这个段的标号,故改成了CZ mov ax, cz ;
将ds指向cz段 mov ds, ax ;
将dl(a和b相对应内存单元内容之和)写入cz中 mov [bx], dl ;
将ds恢复 pop ds ;
递增 inc bx ;bx
loop s
mov ax,4c00h
int 21h code ends
end start
结果分析:
六。编写code段中代码,用push指令将a段中前8个字型数据逆序存储到b段中。
assume cs:code
a segment
a ends
b segment
b ends
程序分析:
最终代码如下:
assume cs:code
a segment
dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh a ends
b segment
dw 0,0,0,0,0,0,0,0 b ends
code segment
start:
mov ax,a
mov ds,ax 指向a段 ;ds
mov ax,b
mov ss,ax 指向了b段 ;ss
16 mov sp, 初始化栈顶,ss:sp指向了栈顶,意味着b段是个栈结构了。 ;
mov bx,0
mov cx,8 ;循环读取a段8次,因为是前8个字 s:
;直接将a段中的字单元内存压栈即可。这样在栈中的存储结构就是逆序的 push ds:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h code ends
end start
运行结果debug:
-d ds:0
0B65:0000
01 00 02 00 03 00 04 00-05 00 06 00 07 00 08 00 ................ 0B65:0010
09 00 0A 00 0B 00 0C 00-0D 00 0E 00 0F 00 FF 00 ................ 0B65:0020
08 00 07 00 06 00 05 00-04 00 03 00 02 00 01 00 ................