8086汇编#6

第六章 包含多个段的程序 – 汇编语言提纲

第六章 包含多个段的程序

第六章 包含多个段的程序

程序取得所需空间的两个方法:在加载程序的时候为程序分配、执行过程中向系统申请(动态内存申请)

6.1 在代码段中使用数据
1.伪指令dw(define word)用于字型数据,每个数据之间以逗号分隔
dd(define dword)用于定义双字数据,db(define byte)用于定义字节型数据
2. 程序的开始处偏移地址为0,dw定义的数据的地址依次递增。

*写汇编程序时,前面写的地址就靠前,后面写的地址靠后

3. 程序默认以CS:0为入口

4. 伪指令 end 标号可以设置程序的入口为某一标号

总结:在代码段使用数据的程序的架构
assume cs:code
code segment
数据
start:;程序入口
代码
code ends
end start
6.2在代码段中使用栈
注:mov 段寄存器,段寄存器 是非法指令

检测点6.1

(1)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,完成程序:
Program test-6-1
assume cs:codesg 
codesg segment 
        dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h 
start:  mov ax,0 
        mov ds,ax 
        mov bx,0 
        mov cx,8 
    s:  mov ax,[bx] 
         mov cs:[bx],ax 
        add bx,2 
        loop s 
        mov ax,4c00h 
        int 21h 
codesg ends 
end start
(2)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行。栈空间设置在程序内。完成程序:
Program test-6-1
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 
start:  mov ax, codesg ;或mov ax, cs 
        mov ss,ax 
        mov sp, 24h ;或mov sp, 36 
        mov ax,0 
        mov ds,ax 
        mov bx,0 
        mov cx,8 
    s:  push [bx] 
         pop cs:[bx] ;或 pop ss:[bx] 
        add bx,2  
        loop s 
        mov ax,4c00h 
        int 21h 
codesg ends 
end start
6.3将数据、代码、栈放入不同的段
1. assume指令可以这样写:assume cs:code,ds:data,ss:stack,es:extra
此时data为数据段stack为栈段,extra为附加段,分别与对应的段关联起来
2. 引用段地址:程序中段名相当于段地址,若程序的assume指令为上面的样子,则mov ax,data将数据段地址送入ax
3. 汇编源程序可以定义许多段,CPU对段中内容的处理取决于汇编代码

实验5 编写、调试具有多个段的程序

(1)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。

program ex-5-1
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 
①CPU执行程序,程序返回前,data段中的数据 不变 。 

②CPU执行程序,程序返回前,CS= 0C88H ,SS= 0C87H ,DS= 0C86H 。

③设程序加载后,CODE段的段地址为X,则DATA段的段地址为 X-2 ,STACK段的段地址为 X-1 。

(2)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。

Program ex-5-2
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 
①CPU执行程序,程序返回前,data段中的数据 不变 。 

②CPU执行程序,程序返回前,CS= 0C88H ,SS= 0C87H ,DS= 0C86H 。

③设程序加载后,CODE段的段地址为X,则DATA段的段地址为 X-2 ,STACK段的段地址为 X-1 。

④对于如下定义的段:

name segment
……
name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为 ((N+15)/16)*16 。

④解析:

N分为被16整除和不被16整除。

当N被16整除时: 占有的空间为(N/16)*16

当N不被16整除时: 占有的空间为(N/16+1)*16,N/16得出的是可以整除的部分,还有一个余数,余数肯定小于16,加上一个16。

程序加载后分配空间是以16个字节为单位的,也就是说如果不足16个字节的也分配16个字节。

两种情况总结成一个通用的公式:((N+15)/16)*16

(3)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。

Program ex-5-3
assume cs:code,ds:data,ss:stack 
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 
data segment 
        dw 0123h,0456h
data ends 
stack segment 
        dw 0,0
stack ends 
end start 
①CPU执行程序,程序返回前,data段中的数据 不变 。 

②CPU执行程序,程序返回前,CS= 0C86H ,SS= 0C8AH ,DS= 0C89H 。

③设程序加载后,CODE段的段地址为X,则DATA段的段地址为 X+3 ,STACK段的段地址为 X+4 。

(4)如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
答:第三条程序仍然可以正确执行,如果不指明入口位置,则程序从所分配的空间开始执行,前2个是数据段,只有从第3条开始是指令代码。
(5)程序如下,编写code段中代码,将a段和b段中的数据依次相加,将结果存到C段中。
Program ex-5-4-1

;程序一:两次循环

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
c segment
    db 0,0,0,0,0,0,0,0
c ends
code segment
start: mov ax,a
       mov ds,ax
       mov ax,b
       mov es,ax
       mov bx,0
       mov cx,8
    s: mov al,[bx]
       add es:[bx],al
       inc bx
       loop s
       mov ax,c
       mov ds,ax
       mov bx,0
       mov cx,8
   s0: mov al,es:[bx]
       mov [bx],al
       inc bx
       loop s0
    mov ax,4c00h
    int 21h
code ends
end start
Program ex-5-4-2

;程序二:一次循环

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
c segment
    db 0,0,0,0,0,0,0,0
c ends
code segment
start: mov ax,a
       mov ds,ax;ds指向a段地址
       mov ax,b
       mov es,ax;es指向b段地址
       mov bx,0
       mov cx,8
    s: mov al,[bx]
       add al,es:[bx]
       mov dx,c
       mov ds,dx;ds指向c段地址
       mov [bx],al
       mov ax,a
       mov ds,ax;重新将ds指向a段(好像此处还能改进)
       inc bx
       loop s
    mov ax,4c00h
    int 21h
code ends
end start
Program ex-5-4-3

;程序三:程序二的改进版

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 
c segment 
        db 0,0,0,0,0,0,0,0 
c ends 
code segment 
start: 
        mov ax,a 
        mov ds,ax 
        mov ax,b 
        mov es,ax 
        mov ax,c 
        mov ss,ax 
        mov bx,0 
        mov cx,8 
s:      mov ax,[bx] 
        mov ss:[bx],ax 
        mov ax,es:[bx] 
        add ss:[bx],ax 
        inc bx 
        loop s
        mov ax,4c00h 
        int 21h 
code ends 
end start
自己的做法
Program ex-5-4-4
mov ax,a
mov ds,ax
mov ax,b
mov es,ax
mov ax,c
mov ss,ax
mov bx,0
mov cx,8
s:mov ax,ds:[bx]
add ax,es:[bx]
mov ss:[bx],ax
inc bx
loop s
mov ax,4c00h
int 21h
(6)程序如下,编写code段中代码,用PUSH指令将A段中的前8个字型数据,逆序存储到B段中。

Program ex-5-5-1

assume cs:code
a segment
    dw 1,2,3,4,5,6,7,8
a ends
b segment
    dw 0,0,0,0,0,0,0,0
b ends
code segment
start: mov ax,a
       mov ds,ax;ds指向a段
       mov ax,b
       mov bx,0;ds:bx指向a段的第1个单元
       mov ss,ax
       mov sp,16;设置栈顶指向b:16
       mov cx,8
    s: push [bx]
       add bx,2
       loop s;将a段中0~16个单元逆次入栈
code ends
end start
自己的做法:
Program ex-5-5-2
mov ax,a
mov ds,ax
mov ax,b
mov ss,ax
mov sp,16
mov dx,0
mov cx,8
s:push ds:[dx]
add dx,2
loop s
mov ax,4c00h
int 21h

发表评论

滚动至顶部