实验3 多个段的汇编源程序编写与调试

一、实验内容
1、实验任务1
使用任意文本编辑器,录入汇编源程序task1.asm。

assume cs:code, ds:data
data segment
        db 'Nuist'
        db 5 dup(2)
data ends

code segment
start:
        mov ax, data
        mov ds, ax            ;ds存储data数据段的段地址

        mov ax, 0b800H        ;b800段属于显存地址范围
        mov es, ax            ;由寄存器es存储

        mov cx, 5             ;loop指令循环次数
        mov si, 0        
        mov di, 0f00h         ;显存地址的段偏移量
s:      mov al, [si]          ;取data数据段第一段的字节数据
        and al, 0dfh          ;转大写
        mov es:[di], al       ;将取出的数据存入到显存地址中
        mov al, [5+si]        ;取data数据段第二段的字节数据
        mov es:[di+1], al     ;存放,此次存放相对于同一次循环中的上次存放,是将数据放在了高位,用于修改输出的内容的颜色
        inc si                ;偏移量加1
        add di, 2             ;显存的段地质偏移量增2
        loop s                ;实现跳转

        mov ah, 4ch
        int 21h
code ends
end start

阅读源程序,从理论上分析源代码的功能,尤其是line15-25,循环实现的功能是什么,逐行理解每条指令的功能。
使用masm、link对task1.asm进行汇编、链接,得到可执行文件task1.exe,运行并观察结果。
使用debug工具对程序进行调试,执行到程序返回前,即line27之前,观察结果。
修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。

db 5 dup(2)
--> 改成:
db 2,3,4,5,6

基于观察,分析、猜测这里的数值作用是什么?

  代码功能:从理论上分析源代码的功能是通过循环将data数据段中的字母转换为大写,同时修改颜色并在显示器上输出。(line15-25指令功能在代码注释中给出)

1、使用masm、link对task1.asm进行汇编、链接,得到可执行文件task1.exe,运行并观察结果。

(1)、编译、连接,如图:

 (2)、运行task1.exe文件(在docbox中运行)

  运行结果中可以发先字符串‘Nuist’被转换为大写,同时字体颜色为绿色显示在doc命令窗口上,验证了理论猜测。

 2、使用debug工具对程序进行调试,执行到程序返回前,即line27之前,观察结果。

  查看data数据段内容,如图:数据段data中的主句如下

 3、修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。运行结果如图:

   修改数据之后,运行结果发生变化,字符的颜色变化为五种不同的颜色。

4、使用debug工具调试,查看data段数据:

 

 

2、实验任务2
已知数据段data中定义字节数据如下:

data segments
db 23, 50, 66, 71, 35
data ends

编写程序,在屏幕上以十进制整数形式打印输出这5个两位数。

assume cs:code
data segment
    db 23, 50, 66, 71, 35
data ends

code segment
start:  
        mov ax, cs
        sub ax, 01h
        mov ds, ax            ;ds存储data数据段的段地址
        mov dh, 10            ;作为除数
                    
        mov si, 0 
        mov cx, 5            ;循环次数
s:      mov ax, [si]        
        mov ah, 00h
        div dh                
        add al, 30h            ;商(低位)
        add ah, 30h            ;余数(高位):数字与其ascii码值差48(30H)
        mov bl, al
        mov bh, ah
        inc si                
        
        mov ah, 2
        mov dl, bl            ;输出十位,bl是待输出的字符,或其ASCⅡ码值
        int 21h
        mov dl, bh            ;输出个位    
        int 21h
        loop s                

        mov ah,4ch
        int 21h

code ends
end start

(1)、编译、连接

(2)、使用debug工具调试:

  1.进入debug,产看相关内容。

 

 

   2.使用g命令和t命令对程序进行调试(以下为一次循环的过程)。

 

 

   3.执行程序(在docbox中执行)

 

 

 

 

3、实验任务3
教材「实验5 编写、调试具有多个段的程序」(1),程序源码参见task3.asm
将下面的程序编译链接,后用debug加载,跟踪,然后回答问题

;task3.asm
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数据段中的数据为多少?

  data段中的数据(0~f)为:23 01 56 04 89 07 BC 0A EF 0D ED 0F BA  0C 87 09

②CPU执行程序,程序返回前,cs=     ,ss=      ,ds=       。

  cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;

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

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

(1)对程序进行编译、连接:

(2)使用debug工具调试程序

  1.使用g命令执行程序到程序退出前:

   执行完g命令后可以查看cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;

在程序中

mov ax,stack  ;将stack的段地址传递给寄存器ss
mov ss, ax
     
mov ax, data  ;将data数据段的地址传递给寄存器ds
mov ds, ax

通过以上代码的功能可知到ss寄存器和ds寄存器的是分别是stack段和data段的段地址(程序执行到最后寄存器都未发生改变,数据段的内容少于16字节),

由stack段、data段、代码段的段地址之间的关系可知道,若cs为X,则ss为X-1,ds为X-2;

  2.使用d指令查看data段中的数据:

data段中的数据(0~f)为:23 01 56 04 89 07 BC 0A EF 0D ED 0F BA  0C 87 09。

 

4、实验任务4
教材「实验5 编写、调试具有多个段的程序」(2),程序源码见task4.asm。

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

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0, 0
stack ends

;task4.asm
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数据段中的数据为多少?

  data段中的数据(0~f)为:23 01 56 04 00 00 00 00 00 00 00 00 00  00 00 00

②CPU执行程序,程序返回前,cs=     ,ss=      ,ds=       。

  cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;

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

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

④对于如下定义的段:

name segment
...
name ends

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

(1)、对程序编译、连接

(2)、使用debug工具调试程序

 

   程序执行到退出前,查看cs,ss,ds的值为:cs=0B68,ss=0B67  ,ds= 0B66 。

  查看data段的数据

 

   前四个字节为23 01 56 04 其余均为0.

(3)、在程序中增加a段

a segment
    dw  0102h,3040h,0506h  ;共6个字节
a ends

(因为name 的意思bai是模块定义伪操作,被系统征用了name这个名字,使用name作为段名出错)

  1.编译连接后使用debug工具调试:

  可发现增加一个段中后程序占用的地址空间就增加10h个字节

  2.使用的指令查看data,stack以及a这三个数据段的值:

  修改as段的数据:dw 0102h, 0304h, 0506h,0102h, 0304h, 0506h,0102h, 0304h, 0506h,增加为9个字数据

 3.编译链接后使用debug调试,再次使用d查段中的数据:

 4.第二次修改:a段的数据修改位18个字数据(36字节)

  编译链接后使用debug调试,再次使用d查段中的数据:

  查看寄存器cx的值发先寄存器的值又增加了10h字节

结论:从以上 结果可发现当段中的数据字节数在十六个字节(八个字数据)以内,该段占用的空间都为十六字节,

   当段中的数据大于16个字节时(设为N)则占用的地址空间为:⌈N/16⌉*16

 

 

5、实验任务5
教材「实验5 编写、调试具有多个段的程序」(3),程序源码见task5.asm。

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

;task5.asm
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数据段中的数据为多少?

  data段中的数据(0~f)为:23 01 56 04 00 00 00 00 00 00 00 00 00  00 00 00

②CPU执行程序,程序返回前,cs=     ,ss=      ,ds=       。

  cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;

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

  通过debug调试发现代码段占用30h个字节,data段的地址为 X + 3   ,stack段的段地址为  X+ 4  。

(1)、对程序编译、连接

(2)、使用debug工具调试程序

   使用g命令执行到程序返回前:从中可查看:cs=0B66,ss=0B6A,ds=0B69.

   使用d指令查看data数据段中的数据:23 01 56 04 00 00 00 00 00 00 00 00 00  00 00 00

 

 

6、实验任务6
教材「实验5 编写、调试具有多个段的程序」(4)

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

(1)修改task3.asm中的伪指令,编译、连接后使用debug指令进行调试:

进行以下操作之后发先task3.asm修改之后不能正确汇编,也不能正确执行。

 

(2)修改task4.asm中的伪指令,编译、连接后使用debug指令进行调试:

结果与task3.asm相同,修改后不能正确汇编,也不能正确执行。

(3)修改task5.asm中的伪指令,编译、连接后使用debug指令进行调试:

  修改过后,只有task5.asm问件在编译链接之后才能进行正确的反汇编,cs寄存器的值才是指令所在段的正确段地址值。 

(4)、对比task3.asm、task4.asm、task5.asm三个文件在各个段的内容:

 cs的值存放的是存储所有段 的段地址,task3和task4都是指令在最后,而task5是指令在最前(第一段)所以在task5中cs的值就是指令所在段的段地址,

只有task5.asm在修改后程序仍然能够执行。

 

 

7、 实验任务7
教材「实验5 编写、调试具有多个段的程序」(5)
程序源码见task7.asm。
注*: 如果在集成软件环境下编写、汇编这个实验任务,请将段名为c的逻辑段,名称改为c1或别的标识
符。由于早期一些指令集中使用c指代寄存器,如不更正,有些汇编器在汇编时会报错。

程序如下:编写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            ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
  db 8 dup(0)
c ends

code segment
start:
    mov ax,cs
    sub ax,0003h
    mov ds,ax

    mov ax,0000h
    mov bx,0000h

    mov cx,4
 s:    mov ax,[bx]
     mov dx,[bx+10h]
     add ax,dx
    mov [bx+20h],ax
    add bx,2
    loop s

    mov ax,4c00h
    int 21h
code ends
end start

(1)、对程序编译、连接

 (2)、使用dubug调试查看程序结果:

 查看c段的内容,a段和b段的值一次相加的结果正确存放到了c段中。

 

 

8、实验任务8
教材「实验5 编写、调试具有多个段的程序」(6),程序源码见task8.asm。
程序如下:编写code段中的代码,用push指令将a段中前8个字型数据逆序存储到c段中。

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 8 dup(0)
b ends

code segment
start: 
    mov ax,cs
    sub ax,1
    mov ss,ax
    mov sp,0010h
    sub ax,2
    mov ds,ax

    mov bx,0000h

    mov cx,8
s:    mov ax,[bx]
    push ax
    add bx,2
    loop s
    
    mov ax,4c00h
    int 21h
code ends
end start

(1)、对程序进行编译、连接

 

(2)、使用debug工具对车光绪进行调试,并查看结果:

posted @ 2020-11-23 20:03  3个月亮  阅读(450)  评论(3)    收藏  举报