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

实验任务1:

task1.asm源代码:

复制代码
assume cs:code, ds:data
data segment
        db 'Nuist'
        db 5 dup(2)        ;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    
复制代码

1、编译、连接:

masm task1.asm; 

link task1.obj;

2、运行结果:屏幕上显示出绿色的全为大写的’NUIST’

3、代码分析:

①运行前查看内存中数据段的内容:

d 076a:0 9          ;DS+10h=076a:代码开始的段地址,0~9数据长度为ah

由结果可知,数据与代码中预存的数据完全一致;

②反汇编查看:

1)理论上:代码长度(CX = 003B)= 数据段(db ‘NUIST’ :5Byte;db 5 dup(2) :5字节)+ 程序段(3b – a = 31)

代码中用end start指定了程序入口,CS:IP理论上应该是:076A:000A,而实际为076B:0000,不一致;

原因:当程序段不足16字节时,将会补足16字节进行存储;所以实际代码段长度为(3B-1)h=2bh;

查看数据:

反汇编指令:

u 0 2a

结果:

反汇编正确;

其中,源代码中的data被编译器处理为一个表示段地址的值,因此也无法直接赋给段寄存器;

③执行到程序返回之前:

④代码理解:

复制代码
 1 assume cs:code, ds:data
 2 data segment
 3         db 'Nuist'
 4         db 5 dup(2)
 5 data ends
 6 
 7 code segment
 8 start:                ;标号start
 9         mov ax, data
10         mov ds, ax
11 
12         mov ax, 0b800H      ;目标段地址设置为显存段地址
13         mov es, ax      
14 
15         mov cx, 5         ;设置循环次数5
16         mov si, 0
17         mov di, 0f00h       
18 s:      mov al, [si]       ;每次循环将Nuist中的字符放入al
19         and al, 0dfh       ;转换为大写:与11011111 标绿位置0,其余位不变
20         mov es:[di], al     ;转换后的字符放入目标地址
21         mov al, [5+si]      ;字符串循环的同时可以依次将取偏移地址为5~9的数据;预设dup(2)对应显示均为绿色
22         mov es:[di+1], al    ;复制入控制颜色的位置;预设dup(2)对应显示均为绿色
23         inc si
24         add di, 2
25         loop s
26 
27         mov ah, 4ch
28         int 21h
29 code ends
30 end start              ;用“end标号”指明源程序中指明程序的入口
复制代码

 ⑤改变第4行代码:

db 2,3,4,5,6        ;db 5 dup(2)

编译、连接,运行结果:

结果:颜色改变了;猜测:这里的数值控制显示的颜色。

实验任务2:

task2.asm源代码:

复制代码
assume cs:code, ds:data
data segment
        db 23,50,66,71,35
data ends

code segment
start:
       mov ax,data
       mov ds,ax

       mov cx,5
       mov si,0
s: mov bl,10 mov ah,0       ;ah要恢复0,否则影响ax作为被除数 mov al,[si] div bl add al,30h add ah,30h mov bx,ax      ;由于输出字符需要访问ah,ah中的结果应先转移 mov ah,2 mov dl,bl int 21h mov dl,bh int 21h inc si loop s mov ah,4ch int 21h code ends end start
复制代码

实验结果截图:

成功输出。

实验任务3:

 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段中数据:
23 01 56 04  ………………执行前后数据段中数据不变 
②CPU执行程序,程序返回前,(SA为代码段起始段地址)
cs = ss+1h    ss = ds+1h    ds = SA+10h
③设程序加载后,code段的段地址为X,则data段的段地址为:X-2h,stack段的段地址为:X-1h

1、查看初始时各个段地址:

SA = 075A

2、反汇编:程序段长:42h-10h-10h = 22h

u 0 21

问题①执行前后数据段内容未发生改变,结论正确:

问题②:实际运行中参照量SA = 075Ah

CS = 076Ch = SS + 1h;SS = 076Bh = DS + 1h;DS = 076Ah = SA + 10h 与理论一致;

问题③:

CS = 076Ch = X;SS = 076Bh = CS - 1h;DS = 076Ah = CS - 2h 与理论一致。

实验任务4:

 task4.asm源代码:

复制代码
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段中数据:
23 01 56 04
②CPU执行程序,程序返回前,(SA为代码段起始段地址)
cs = ss+1h    ss = ds+1h    ds = SA+10h
③设程序加载后,code段的段地址为X,则data段的段地址为:X-2h,stack段的段地址为:X-1h
④如果段中数据占N个字节,程序加载后,该段实际占有的空间:若N%16==0 实际N字节;否则,实际存储(N/16+1)*16字节。
复制代码

前三个问题:同实验3:

由task4的运行截图可知:

结论完全一致;

问题④:task4代码中data段和stack段均不足16个字节,实际加载时,每段都补足了16字节;

将代码改变如下:

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h,0123h, 0456h,0123h, 0456h,0123h, 0456h,0123h, 0456h    ;data段设置20个字节
data ends
…………………………        ;其余均不变

运行结果对比:

data段数据20字节,实际存储却为2H(32字节);

结论:段的存储长度为16字节的整数倍,不足的补全16字节的再存储。

实验任务5:

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段中数据:
23 01 56 04不变
②CPU执行程序,程序返回前,(SA为代码段起始段地址)
cs = SA+10H    ss = DS+1H    ds = CS+3H    
③设程序加载后,code段的段地址为X,则data段的段地址为:X+3,stack段的段地址为:X+4

 运行结果:

反汇编:

CS  = 076A  DS = 076D = CS + 3H  :意味着代码段实际存储内存为30H,而反汇编依然是22H字节即为完整代码,可以推测,代码段中不足16个字节的部分补足16字节进行存储;

SS = DS + 1H  :data段数据实际存储为10H个字节;

且由运行结果可知:CX = 0042H–》CX = 0044H,则栈段实际存储 44H – 30H – 10H = 4H 为源代码中预留栈段的实际长度,并未补齐16字节存储;

由实验结果可以推测,源代码在程序加载后,只有最后一个程序段不进行补齐16字节存储的操作。

执行:

实验结果与理论一致。

实验任务6:

问题:

实验任务5中代码仍然可以正确执行,因为默认CS = SA + 10H,只有实验任务5中的代码此时的CS为程序段正确的起始段地址;

实验结果:

task3,删去代码最后的start后编译、连接追踪运行结果:

CS未指向正确的程序开始,第一条代码也错误,代码中也没有重定向CS的代码;

task4,删去代码最后的start后编译、连接追踪运行结果:

结果同上;

task5,删去代码最后的start后编译、连接追踪运行结果:

CS指向程序入口,反汇编成功,仍然可以执行;

实验结果与理论猜测一致。

实验任务7:

task7.asm源代码:

复制代码
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,a
    mov ds,ax
    mov ax,c
    mov es,ax
    mov cx,8
    mov si,0
    
s:    mov al,ds:[si]
    add al,ds:[si+16]
    mov es:[si],al
    inc si
    mov al,0
    loop s

    mov ax,4c00h
    int 21h
code ends
end start
复制代码

运行结果:

①编译、连接,跟踪运行、反汇编:

 ②在运行前查看3段数据,g命令运行到返回前,查看运行后结果:

实验成功。

实验任务8:

task8.asm源代码:

复制代码
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,a
    mov ds,ax
    mov ax,b
    mov ss,ax
    mov sp,10h
    
    mov cx,8
    mov si,0eh

s:    mov ax,ds:[si]
    push ax                
    dec si
    dec si
    loop s
    
    mov ax,4c00h
    int 21h
code ends
end start
复制代码

编译、连接、跟踪运行,反汇编查看:

运行前后查看内存内容:

实验成功。

类似文章