《汇编语言》实验5 编写、调试具有多个段的程序

第 (1) 题

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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段中的数据 为多少?


保持不变。

分析
   程序中先把栈顶指向了 stack段的空栈位置,即:ss=stack sp=10H。然后把ds指向数据data段,从ds[0]ds[2] 两个字的数据 push到栈中,然后pop[2][0]把数据 从栈中取出,因为pop时偏移位置与push时调换了位置,所以传入到 data段中的数据还和原始一致。如还有疑问可参考3.6相关知识点。

问题 ②

CPU执行程序,程序返回前,cs=____ 、ss=、ds=


cs=076E 、ss=076D、ds=076C

分析
不同计算机执行的时候这些数值会不一样,根据Debug的实际情况填写内容。

问题 ③

设程序加载后,code段的段地址为X,则data段的段地址为____,stack段的段地址为____。


data段的段地址为 X-2H,stack段的段地址为 X-1H。

分析
程序中段的位置依次为data、stack、code,data与stack声明的大小均为16Byte,则可以计算出stack段地址为 X-16Byte = X-1H,data段地址为 X-stack-16Byte = X-2H。

第 (2) 题

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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段中的数据 为多少?


保持不变。

分析
与(1).① 相同

问题 ②

CPU执行程序,程序返回前,cs=____ 、ss=____ 、ds=____


cs=076E 、ss=076D、ds=076C

分析
与(1).② 相同

问题 ③

设程序加载后,code段的段地址为X,则data段的段地址为____,stack段的段地址为____。


data段的段地址为 X-2H,stack段的段地址为 X-1H。

分析
因为代码在data与stack段中的声明了2个字单元,但是因为每个段的必需是16的位数也就是说第个段的大小至少16Byte,所以与(1)中代码声明的data、stack所占用的空间大小是一样的都是16Byte,则相对于code段的偏移位置也是一样的。

问题 ④

对于如下定义的段:

1
2
3
name segment
.
name ends

如果段中的数据占N个字节,则程序加载后,该段实际占用的空间为 ____ 。


该段实际占用的空间为 ceil(N/16.0)*16Byte

分析
由于段地址必需是16倍数,所以实际占用空间为 N除16 向上取整再乘以16Byte

第 (3) 题

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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=____ 、ss=、ds=


cs=076C 、ss=0770、ds=076F

分析
与(1).② 相同

问题 ③

设程序加载后,code段的段地址为X,则data段的段地址为____,stack段的段地址为____ 。


data段的段地址为 X+3H,stack段的段地址为 X+4 。

分析
用R命令可以看到CX=44H(程序的总长度),data与stack共占用20H长度,则code段的长度为44H-20H=24H,因为段地址必需按16Byte对齐则实际占用的空间为30H,所以data段为X+3H,stack段为X+4H

第 (4) 题

如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序 仍然可以正确执行?请说明原因。


都能执行,但只有程序(3)可以正确执行,因为程序 加载后会从程序第一个单元开始执行,但只有(3)中的code段在程序 的开始位置,所以所以只有(3)中的程序 是可以正确执行的。

第 (5) 题

程序如下,编写code段中的代码,将a段和b段 中的数据依次相加,将结果存到c段中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
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:
        ?
code ends
end start

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
assume cs:code

a segment
    db 1,2,3,4,5,6,7,8  ; db定义字节单元数据 、dw字义字单元数据、dd定义双字单元数据 
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        ; 循环次数8次
s:  
    mov dl,ds:[bx]  ; 把a段当前偏移位置的数值传送到dl
    add dl,es:[bx]  ; 把b段当前偏移位置的数值加到dl中

    push ds         ; 因为后面要用ds定位c段的数据,这里先把ds放入到栈中后续再取出复原到a段

    mov ax,c       
    mov ds,ax       ; ds定位到c段
    mov [bx],dl     ; 把dl数值传送到c段的偏移位置

    pop ds          ; 恢复之前存储的ds数值

    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends

end start

第 (6) 题

程序如下,编写code段中的代码,用push指令将a段的前8个字型数据,逆序存储到b段中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
assume cs:code

a segment
    dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,oeh,ofh,offh
a ends

b segment
    dw 0,0,0,0,0,0,0,0
b ends

code segment
start:
        ?
code ends

end start

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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

    mov ax,b
    mov ss,ax
    mov sp,10h

    mov bx,0
    mov cx,8
s:
    push [bx]
    add bx,2
    loop s
    
    mov ax,4c00h
    int 21h

code ends

end start