实验 2 多个逻辑段的汇编源程序编写与调试


实验 2 多个逻辑段的汇编源程序编写与调试

实验结论

1. 实验任务 1

  • 任务 1-1

    • task1_1.asm 源码

      assume ds:data, cs:code, ss:stack
      
      data segment
          db 16 dup(0)
      data ends
      
      stack segment
          db 16 dup(0)
      stack ends
      code segment
      start:
          mov ax, data
          mov ds, ax
      
          mov ax, stack
          mov ss, ax
          mov sp, 16
      
          mov ah, 4ch
          int 21h
      code ends
      end start
      
    • task1_1 调试到 line17 结束、line19 之前截图

    • 问题回答
      ① 在 debug 中将执行到 line17 结束、line19 之前,记录此时:寄存器(DS) = 076C, 寄存器(SS) = 076D, 寄存器(CS) = 076E
      ② 假设程序加载后,code 段的段地址是 X,则,data 段的段地址是 X-2, stack 的段地址是 X-1

  • 任务 1-2

    • 任务 task1_2.asm 源码

      assume ds:data, cs:code, ss:stack
      
      data segment
          db 4 dup(0)
      data ends
      
      stack segment
          db 8 dup(0)
      stack ends
      code segment
      start:
          mov ax, data
          mov ds, ax
      
          mov ax, stack
          mov ss, ax
          mov sp, 8
      
          mov ah, 4ch
          int 21h
      code ends
      end start
      
    • task1_2 调试到 line17 结束、line19 之前观察寄存器 DS, CS, SS 值的截图。

    • 问题回答
      ① 在 debug 中将执行到 line17 结束、line19 之前,记录此时:寄存器(DS) = 076C,寄存器(SS) = 076D, 寄存器(CS) = 076E

      ② 假设程序加载后,code 段的段地址是 X,则,data 段的段地址是 X-2 stack 的段地址是 X-1

段占用空间连续且为 16 字节的整数倍。

  • 任务 1-3
    • 任务 task1_3.asm 源码

      assume ds:data, cs:code, ss:stack
      
      data segment
          db 20 dup(0)
      data ends
      
      stack segment
          db 20 dup(0)
      stack ends
      code segment
      start:
          mov ax, data
          mov ds, ax
      
          mov ax, stack
          mov ss, ax
          mov sp, 20
      
          mov ah, 4ch
          int 21h
      code ends
      
    • task1_3 调试到 line17 结束、line19 之前观察寄存器 DS, CS, SS 值的截图

    • 问题回答
      ① 在 debug 中将执行到 line17 结束、line19 之前,记录此时:寄存器(DS) = 076C, 寄存器(SS) = 076E, 寄存器(CS) = 0770
      ② 假设程序加载后,code 段的段地址是 X,则,data 段的段地址是 X - 4, stack 的段地址是 X - 2

  • 任务 1-4
    • 任务task1_4.asm源码

      assume ds:data, cs:code, ss:stack
      code segment
      start:
          mov ax, data
          mov ds, ax
      
          mov ax, stack
          mov ss, ax
          mov sp, 20
      
          mov ah, 4ch
          int 21h
      code ends
      
      data segment
          db 20 dup(0)
      data ends
      
      stack segment
          db 20 dup(0)
      stack ends
      end start
      
    • task1_4调试到line17结束、line19之前观察寄存器DS, CS, SS值的截图

    • 问题回答
      ① 在debug中将执行到line9结束、line11之前,记录此时:寄存器(DS) = 076E, 寄存器(SS) = 0770, 寄存器(CS) = 076C
      ② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X + 2, stack的段地址是 X + 4

  • 任务1-5
    • 基于上述四个实验任务的实践、观察,总结并回答:
      ① 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是 $\lceil N / 16 \rceil$(向上取整)。
      xx segment
      db N dup(0)
      xxx ends
      
      ② 如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成 end , 哪一个程序仍然可以正确执行。结合实践观察得到的结论,分析、说明原因。
      • task1_5.asm 可以运行,其代码段位于程序首部;

2. 实验任务 2

编写一个汇编源程序,实现向内存单元b800:0f00 ~ b800:0f9f连续160字节,依次重复填充十六进制数据03 04。

在debug中,使用f命令,向内存单元批量填写数据。
-f b800:0f00 0f9f 03 04
把内存单元区间b800:0f00 ~ b800:0f9f连续160个字节,依次重复填充十六进制数据03 04。

  • 汇编源代码

    ASSUME CS:CODE
    
    CODE SEGMENT
        MOV AX, 0B800H
        MOV DS, AX
    
        MOV BX, 0F00H
        MOV AX, 0403H
        MOV CX, 009FH
    s:  MOV [BX], AX
        INC BX
        LOOP s
    
        MOV AX, 4C00H
        INT 21H
    CODE ENDS
    
    END
    
  • 运行结果截图

3. 实验任务 3

已知 8086 汇编源程序 task3.asm 代码片段如下。
task3.asm

要求:
① 编程实现把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中。
② 在debug中加载、反汇编、调试。在数据项依次相加前,和相加后,分别查看三个逻辑段data1, data2, data3对应的内存空间,确认逐一相加后,结果的确保存在了逻辑段data3中。

  • 补充完整后的汇编源代码

    assume cs:code
    data1 segment
        db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
    data1 ends
    
    data2 segment
        db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0       ; ten numbers
    data2 ends
    
    data3 segment
        db 16 dup(0)
    data3 ends
    
    code segment
    start:
        mov ax, data1
        mov ds, ax
    
        mov bx, 0
        mov si, 16
        mov di, 32
        mov cx, 10
    s:  mov ax, [bx]
        add ax, [si]
        mov [di], ax
        inc bx
        inc si
        inc di
        loop s
    
        mov ax, 4C00H
        int 21H
    code ends
    end start
    
  • 在debug中加载、反汇编、调试截图

    • 要求给出,在数据项依次相加之前,查看逻辑段data1, data2, data3对应的内存空间数据原始值的debug命令和截图

    • 以及,依次相加之后,查看逻辑段data1, data2, data3对应的内存空间数据原始值的debug命令和截图

4. 实验任务4

  • 补充完整后的汇编源代码

    assume cs:code
    
    data1 segment
        dw 2, 0, 4, 9, 2, 0, 1, 9
    data1 ends 
    
    data2 segment
        dw 8 dup(?)
    data2 ends
    
    code segment
    start:
        mov ax, data1
        mov ds, ax
    
        mov si, 0
        mov di, 1eh
        mov cx, 8
    
    s:  mov ax, [si]
        mov [di], ax
        add si, 2
        sub di, 2
        loop s
    
        mov ah, 4ch
        int 21h
    code ends
    end start
    
  • 在debug中加载、反汇编、调试截图

  • 要求给出,在程序退出前,使用d命令查看数据段data2对应的内存空间的截图。

5. 实验任务5

  • task5.asm 源码

    assume cs:code, ds:data
    data segment
            db 'Nuist'
            db 2, 3, 4, 5, 6
    data ends
    
    code segment
    start:
            mov ax, data
            mov ds, ax
    
            mov ax, 0b800H
            mov es, ax
    
            mov cx, 5
            mov si, 0
            mov di, 0f00h
    s:      mov al, [si]
            and al, 0dfh
            mov es:[di], al
            mov al, [5+si]
            mov es:[di+1], al
            inc si
            add di, 2
            loop s
    
            mov ah, 4ch
            int 21h
    code ends
    end start
    
  • 运行结果截图

  • 使用debug工具对程序进行调试,使用g命令一次性执行到程序返回前(即 line25 执行之后、line27 执行之前)的截图

  • 源代码中line19的作用是?

    • 将小写字符 ASCII 码通过与运算 (AND 1101 1111) $(DF)_16 = (1101 1111)_2$ 转换为大写字符 对应的 ASCII 码
    • A-Z 0100 0001 ~ 0101 1010
    • a-z 0110 0001 ~ 0111 1010
  • 源代码中 data 段 line4 的字节数据的用途是?

    • 通过尝试修改数据段中第二段数字,猜测其决定对应字符的显示颜色

6. 实验任务 6

要求:
① 补全程序,将data段中的每行第一个单词从大写->小写。
② 在debug中加载程序,反汇编,执行到 line13 退出前,用 d 命令查看 data 段对应的内存空间,确认每行第一个单词已经由大写->小写。

  • task6.asm 源代码

    assume cs:code, ds:data
    
    data segment
        db 'Pink Floyd      '
        db 'JOAN Baez       '
        db 'NEIL Young      '
        db 'Joan Lennon     '
    data ends
    
    stack segment
        db 16 dup(?)
    stack ends
    
    code segment
    start:
        mov ax, data
        mov ds, ax
        mov ax, stack
        mov ss, ax
    
        mov cx, 4
        mov bx, [0]
    s1: 
        push cx
            mov cx, 4
        s2: mov al, [bx]
            or al, 20h
            mov [bx], al
            inc bx
            loop s2
        add bx, 12
        pop cx
        loop s1
    
        mov ah, 4ch
        int 21h
    code ends
    end start
    
    • 通过 ASCII 码将大写字符转换为小写字符需要或 0010 0000 即 $20H$
      • A-Z 0100 0001 ~ 0101 1010
      • a-z 0110 0001 ~ 0111 1010
  • 在 debug 中加载、反汇编、调试截图

    • 要求给出,在程序退出前,使用 d 命令查看数据段 data 对应的内存空间的截图。

7. 实验任务 7

  • task7.asm源码

    assume cs:code, ds:data, es:table
    
    data segment
        db '1975', '1976', '1977', '1978', '1979' 
        dw  16, 22, 382, 1356, 2390
        dw  3, 7, 9, 13, 28 
    data ends
    
    table segment
        db 5 dup( 16 dup(' ') )  ;
    table ends
    
    stack segment
        db 16 dup(?)
    stack ends
    
    code segment
    start:
        mov ax, data
        mov ds, ax
        mov ax, table
        mov es, ax
        mov ax, stack
        mov ss, ax
    
        mov bx, 0
        mov di, 0
        mov cx, 5
    s1: push cx
        mov cx, 4
        s2: mov al, [bx]
            mov es:[di], al
            inc bx
            inc di
            loop s2
        add di, 12
        pop cx
        loop s1
    
        mov di, 0
        mov bx, 0
        mov cx, 5
    s3: mov ax, [20 + bx]
        mov es:[di + 5], ax
        mov dl, [30 + bx]
        div dl
        mov ah, 0
        mov es:[di + 13], ax
        mov ax, [30 + bx]
        mov es:[di + 10], ax
        add di, 10h
        add bx, 2
        loop s3
    
        mov ah, 4ch
        int 21h
    code ends
    end start
    
    • 循环 s1 遍历表格中每一行的年份,s2 遍历年份的每一个字符,将其赋值至 table 每行行首
    • 循环 s3 遍历表格中每一行的数据,每一个数据占 2 字节(1 机器字)
      • di 为每行行首地址
        • di + 5 为收入地址,20 + bx 为数据段中收入地址
        • di + 10 为雇员人数地址,30 + bx 为数据段中雇员人数地址
        • di + 13 为人均收入地址
      • 16 bit / 8 bit 除法,被除数为 ax, 将商存在 al 余数存在 ah
  • 调试截图

    • 查看 table 段原始数据信息截图

    • 在 debug 中运行到程序退出之前,使用 d 命令查看 table 段对应的内存空间的截图,确认信息是否按要求结构化地写入到指定内存