汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

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

assume cs:code,ds:data,ss:stack
data segment
    dw 0123,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段中的数据为多少?

解答:我们先用debug加载跟踪一下看看结果如何

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

 在程序刚载入内存时,由于还没有执行设定数据段地址的指令(mov ds,data),DS段地址默认指向程序起始位置(包括PSP数据区),此时 DS:0~DS:FF 为PSP数据区(占256个字节),DS:100 开始为数据段、栈段、代码段内容。(如上图)

在执行了mov ds,data 指令后,数据段被手工设定为 DS:0~D:F为数据段(DS段地址已经被更改)(如下图)但在设定逻辑上的数据段前后,物理上的数据段是始终没有发生改变的,始终处于 1299:0~1299:f 部分

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

 由实验结果可知,data段中的数据为

23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09

②CPU执行程序,程序返回前,CS = ______ 、SS= ______ 、DS= ______

执行到 mov ax,4c00h指令时,各寄存器内容如下

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答  由实验结果可知 CS = 129B ,SS = 129A,DS = 1299

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

由②可知 DS = CS - 2,SS = CS - 1。

故 data 段地址为 X - 2,stack 段地址为 X - 1

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

assume cs:code,ds:data,ss:stack
data segment
    dw 0123,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段中的数据为多少?

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

注意:数据段和栈段在程序加载后实际占据的空间都是以 16 个字节为单位的,如果不足,以 0 补全填充

 由实验结果可知,data段中的数据为

23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00

② CPU执行程序,程序返回前,CS = ______ 、SS= ______ 、DS= ______

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

 由实验结果可知 CS = 129B ,SS = 129A,DS = 1299

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

这里与(1)大致相同,因为段的结构顺序和大小是大致相同的

由②可知 DS = CS - 2,SS = CS - 1。

故 data 段地址为 X - 2,stack 段地址为 X - 1

④ 对于如下定义的段:

name segment

...

name ends

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

如果N小于16,那么实际占用16个字节;如果N大于16,那么实际占用(N/16的取整数+1)*16个字节。即如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为  汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

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

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 0123,0456h
data ends
stack segment
    dw 0,0
stack ends
end start

① CPU执行程序,程序返回前,data段中的数据为多少?

(3)与(1)(2)所不同的是(3)将数据段和栈段放到了代码段的后面

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答  由实验结果可知,data段中的数据为

23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00

② CPU执行程序,程序返回前,CS = ______ 、SS= ______ 、DS= ______

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

  由实验结果可知 CS = 1299 ,SS = 129D,DS = 129C

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

由②可知 DS = CS + 3,SS = CS =+ 4

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

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

在程序设计中,我们用伪指令end描述了程序的结束和程序的入口。在编译链接后,由“end start”指明的程序入口,被转化为一个入口地址,我们可以发现在程序中设置了start 和 end start 后 程序执行时会从 start 位置开始,到 end start 位置结束。如果不设 end start ,只设置 end 。那么此时程序会默认从 PSP数据区后开始执行(即使设置了start,程序也不会从start位置开始执行)。如果要保证程序正常执行,那么在PSP数据区之后必须为代码段才行。由(1)(2)(3)三个程序可知只有程序(3)代码段在前面,故最后一条伪指令“end start”改为“end”后,程序(3)仍然可以正确执行

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

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 segment
code segment
start:
    ___________
code ends
end start

这里首先要注意的是,a 段、b 段和 c 段的数据都是按字节存放的,所以在使用寄存器转移数据时一定要使用 8 位寄存器而不是 16 位寄存器!不然就有可能引起错误(虽然本题使用 16 位寄存器与使用 8 位寄存器结果一样,但一定要规范)。

这里笔者使用的思想是使用 DS 存储 a 段地址,b 段地址可以直接使用 DS + 16 表示(a 段不足16个字节用 0 补上后占 16 个字节) ES 存储 c 段地址,每次循环将 a 段和 b 段的一个字节相加后存入 c 段中即可

代码如下:

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,c
      mov es,ax    ; es 存放 c 段地址
      
      mov bx,0
      mov cx,8     ;  对字进行 8 次循环操作

s0:
      mov dl,[bx]
      add dl,[bx+16]    // a 段不足16个字节用0补上后占16个字节
      mov es:[bx],dl    // a + 16 后即为 b 段地址
      inc bx
      loop s0
      
      mov ax,4c00h
      int 21h

code ends

end start

实验结果如下:

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

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

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:
    __________
code ends
end start

本题与上一题有所不同,本题是数据是按字存储的,故使用 16 位寄存器。

要求使用 push 指令将前 8 个字型数据存储到 b 段中,这里应当a段为数据段、 b 段为栈段才能使用 push 指令将 a 段的数据压入 b 段中,循环 8 次即可

代码如下:

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    ;DS 存放 a 段地址
      
      mov ax,b
      mov ss,ax    ;SS 存放 b 段地址(栈段)
      mov sp,10h

      mov bx,0    
      mov cx,8

s0:
      push [bx]    ; a 段数据压入 b 段
      inc bx       ; 由于字占 16 位,一个内存单元占 8 位
      inc bx       ; 故每次循环 + 2 才能指到下一个字
      loop s0
      
      mov ax,4c00h
      int 21h

code ends

end start

实验结果如下:

汇编语言(第四版)实验5 编写、调试具有多个段的程序解答

上一篇:【Linux】CentOS系统下lsb_release: 未找到命令


下一篇:不同的时间区间取并集