实验4 汇编应用编程和c语言程序反汇编分析

------------恢复内容开始------------

实验任务一:

 1 assume cs:code, ds:data, ss:stack
 2 
 3 data segment
 4     db 'welcome to masm!'
 5     db 2h,24h,71h           ;三行文字的颜色
 6 data ends
 7 
 8 stack segment
 9     db 16 dup (0)
10 stack ends
11 
12 code segment
13 start:
14         mov ax,data
15         mov ds,ax          ;代码段的段始址送到ds
16         
17         mov ax,stack
18         mov ss,ax
19         mov sp,16         ;栈段的栈顶指针指向ss:16
20     
21         mov ax,0B87Ch    ;将字符串显示在屏幕中间的位置
22         mov es,ax
23 
24         mov cx,3             ;三行的显示代码是外层循环三次
25         mov bx,0             ;记录当前是第几行,也是外层循环的次数
26 
27 s:      push cx
28         mov cx,16           ;每行显示16个字符,内存循环16次
29         mov di,0              ;记录内存循环的次数
30 
31 s0:    mov al,ds:[di]        ;低字节显示文字
32         mov ah,ds:[bx+16] ;高字节显示颜色属性
33         mov si,di
34         add si,si
35         mov es:[si],ax
36         inc di
37         loop s0
38 
39         pop cx
40         mov ax,es
41         add ax,00ah          ;切换到下一行的位置
42         mov es,ax
43         inc bx
44         loop s
45        
46         mov ax,4c00h
47         int 21h
48 code ends
49 end start

运行结果为:

在一页显示缓冲区中:

偏移000~09F对应显示器上的第1行(80个字符占160个字节);

偏移0A0~13F对应显示器上的第2行;

偏移140~1DF对应显示器上的第3行;

以此类推,可知偏移780~81F对应显示器上的第12行。

在一行中,一个字符占两个字节的存储空间(一个字),低位字节存储字符的ASCLL码,高位字节存储字符的属性。一行共有80个字符,占160个字节。

即在一行中:

00~01单元对应显示器上的第1列;

02~03单元对应显示器上的第2列;

04~05单元对应显示器上的第3列;

依此类推,可知,40~41单元对应显示器上的第30列。

因此字符串首地址设为:B878*16+40=B87Ch

黑底绿字,属性字节为:00000010

绿底红字,属性字节为:00100100

白底蓝字,属性字节为:01110001

注意:在显示缓冲区中,偶地址存放字符,奇地址存放字符的颜色属性

 

实验任务二:

 1 assume cs:code, ds:data
 2 data segment
 3     str db 'another try', 0          ;定义以0结尾的字符串try
 4 data ends
 5 
 6 code segment
 7 start:  
 8     mov ax, data
 9     mov ds, ax
10 
11     mov si, offset str       ;offset操作符取得了str的偏移地址0
12     mov al, 4
13     call printStr            ;跳转指令,跳转到printStr处执行
14 
15     mov ah, 4ch
16     int 21h
17 
18 printStr:
19     push bx                  ;将寄存器压入栈,子程序中可能会用到这些寄存器
20     push cx
21     push si
22     push di
23 
24     mov bx, 0b800H
25     mov es, bx
26     mov di, 0
27 s:              mov cl, [si]
28     mov ch, 0
29     jcxz over                 ;cx为0时,指令跳转到over处执行
30     mov ch, al
31     mov es:[di], cx
32     inc si
33     add di, 2
34     jmp s
35 
36 over:   pop di                 ;将寄存器出栈,恢复寄存器原先的值
37     pop si
38     pop cx
39     pop bx
40     ret
41 
42 code ends
43 end start

运行结果为:

对源程序做如下修改:
把line3改为: str db 'another try', 0
把line12改为: mov al, 4 
汇编,链接,观察运行结果为:
基于运行结果,理解源代码,以及,组合使用转移指令call和ret实现子程序的原理与方法。具体地,在line18-40中:
line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?
答:由于寄存器数量有限,子程序中可能会使用到这些寄存器,但是我们不确定这些寄存器中是否存储了重要的信息,因此先将寄存器bx,cx,si,di压入栈,在子程序中就可以随意使用这些寄存器,子程序执行完毕,将寄存器出栈,出栈的同时寄存器也会恢复原来的值。
line30的功能是什么?
答:line 30行的内容是mov ch, al,在line 12中有一条指令mov al, 4,这两条指令表示将4送入到ch中,根据之前的实验可知,高位字节存放的是数据的颜色属性,因此line 30行的功能是改变数据的颜色属性。
 
实验任务三:
 1 assume cs:code, ds:data
 2 data segment
 3         x dw 1984               ;定义x为一个字变量赋初值为1984
 4         str db 16 dup(0)     ;定义str为一个byte数组,存放16个字节的0
 5 data ends
 6 
 7 code segment
 8 start:  
 9         mov ax, data
10         mov ds, ax
11         mov ax, x
12         mov di, offset str
13         call num2str
14 
15         mov ah, 4ch
16         int 21h
17 
18 num2str:
19         push ax
20         push bx
21         push cx
22         push dx
23         
24         mov cx, 0
25         mov bl, 10
26 s1:      
27         div bl
28         inc cx
29         mov dl, ah
30         push dx
31         mov ah, 0
32         cmp al, 0
33         jne s1
34 s2:        
35         pop dx
36         or dl, 30h
37         mov [di], dl
38         inc di
39         loop s2
40         
41         pop dx
42         pop cx
43         pop bx
44         pop ax
45 
46         ret
47 code ends
48 end start

子任务一:

汇编,链接之后对该程序用u命令进行反汇编,用g命令执行到mov ah,4ch,用d命令查看执行之后的结果,发现把转换后的数字字符串'1984'存放在数据段中str标号后面的单元。

子任务二:

 1 assume cs:code, ds:data
 2 data segment
 3         x dw 1984               ;定义x为一个字变量赋初值为1984
 4         str db 16 dup(0)     ;定义str为一个byte数组,存放16个字节的0
 5 data ends
 6 
 7 code segment
 8 start:  
 9         mov ax, data
10         mov ds, ax
11         mov ax, x
12         mov di, offset str
13         call num2str
14         mov si, offset str
15         call printStr
16 
17         mov ah, 4ch
18         int 21h
19 
20 num2str:
21         push ax
22         push bx
23         push cx
24         push dx
25         
26         mov cx, 0
27         mov bl, 10
28 s1:      
29         div bl
30         inc cx
31         mov dl, ah
32         push dx
33         mov ah, 0
34         cmp al, 0
35         jne s1
36 s2:        
37         pop dx
38         or dl, 30h
39         mov [di], dl
40         inc di
41         loop s2
42         
43         pop dx
44         pop cx
45         pop bx
46         pop ax
47 
48         ret
49 
50 printStr:
51     push bx
52     push cx
53     push si
54     push di
55 
56     mov bx, 0b800H
57     mov es, bx
58     mov di, 0
59 s:             
60                 mov cl, [si]
61     mov ch, 0
62     jcxz over
63     mov ch, al
64     mov es:[di], cx
65     inc si
66     add di, 2
67     jmp s
68 
69 over:       pop di
70     pop si
71     pop cx
72     pop bx
73     ret
74 code ends
75 end start

运行结果为:

将line3中的整数改为1234,汇编,链接,运行结果为:

将line3中的整数改为2020,汇编,链接,运行结果为:

 通过实验发现,修改数字之后,输出的字符颜色及属性都不相同。

 

实验任务四:

 1 assume cs:code, ds:data
 2 data segment
 3         str db 80 dup(?)
 4 data ends
 5 
 6 code segment
 7 start:  
 8         mov ax, data
 9         mov ds, ax
10         mov si, 0
11 
12 s1:        
13         mov ah, 1
14         int 21h
15         mov [si], al
16         cmp al, '#'
17         je next
18         inc si
19         jmp s1
20 next:
21         mov cx, si
22         mov si, 0
23 s2:     mov ah, 2
24         mov dl, [si]
25         int 21h
26         inc si
27         loop s2
28 
29         mov ah, 4ch
30         int 21h
31 code ends
32 end start

运行结果为:

汇编、链接、运行程序,输入一个字符串并以#结束(比如,2020, bye#)观察运行结果。结合运行结
果,理解程序功能,了解软中断指令。具体地:
line12-19实现的功能是?
答:循环执行将输入的单个字符写入内存单元中,遇到#跳转到next处执行。
line21-27实现的功能是?
答:循环执行输出单个字符。
 
实验内容五:

 

 

通过断点设置,查看反汇编代码,发现在c=sum(a,b)处的汇编指令先将b移到eax寄存器中,将eax压栈,将a移到ecx寄存器中,将ecx压栈,接着跳转到048116Dh处执行,并将此时的add esp,8的偏移地址压栈,被调函数也可以使用eax、edx、ecx这三个寄存器,所以规定调用者需保存eax、edx和ecx,在从被调函数返回后先恢复这三个寄存器的值再继续;被调用者保存ebx、esi和edi这三个寄存器,对他们进行压栈处理,执行完之后,进行出栈操作,遇到ret指令时,继续回到call指令的下一条指令执行。

 

 

 

 

------------恢复内容结束------------

posted @ 2020-12-12 20:40  xiqingyu  阅读(142)  评论(1)    收藏  举报