汇编语言程序设计第四次实验 汇编应用编程和C语言程序反汇编分析

时间:2020-12-18 13:01:52   收藏:0   阅读:3

一、实验目的

1. 理解80×25彩色字符模式显示原理

2. 理解转移指令jmp, loop, jcxz的跳转原理,掌握使用其实现分支和循环的用法

3. 理解转移指令call, ret, retf的跳转原理,掌握组合使用call和ret/retf编写汇编子程序的方法,掌握 参数传递方式

4. 理解标志寄存器的作用

5. 理解条件转移指令je, jz, ja, jb, jg, jl等的跳转原理,掌握组合使用汇编指令cmp和条件转移指令实 现分支和循环的用法

6. 了解在visual studio/Xcode等环境或利用gcc命令行参数反汇编c语言程序的方法,理解编译器生成 的反汇编代码

7. 综合应用寻址方式和汇编指令完成应用编程

二、实验准备

实验前,请复习/学习教材以下内容:

第9章 转移指令的原理

第10章 call和ret指令

第11章 标志寄存器

三、实验内容

四、实验结论

1.实验任务1

首先分析三种样式对应的属性字节,绿色对应02h,绿底红色对应24h,白底蓝色对应71h。

其次根据80×25彩色符号模式,确定出显示的位置。

技术图片

 实验代码:

 1 assume cs:code,ds:data
 2 
 3 data segment
 4     db welcome to masm!
 5     db 2h,24h,71h
 6 data ends
 7 
 8 code segment
 9 start:
10     mov ax,data
11     mov ds,ax
12 
13     mov ax,0B872h
14     mov es,ax
15 
16     mov cx,3    ;记录还需要输出的行数
17     mov bx,0    ;记录每个颜色相对于第一个颜色数据的偏移地址
18 
19  s0:push cx        ;利用栈保存cx的值
20     mov cx,16
21     mov di,0    ;记录字符的偏移地址
22     mov si,0    ;记录一行中字符显示的位置
23 
24  s1:mov al,ds:[di]
25     mov ah,ds:[16+bx]
26     mov es:[si],ax
27     add si,2
28     inc di
29     loop s1
30 
31     pop cx
32     mov ax,es    ;借助寄存器,修改段寄存器中的值,切换到下一行
33     add ax,00ah
34     mov es,ax
35     inc bx
36     loop s0
37 
38     mov ax,4c00h
39     int 21h
40     
41 code ends
42 end start

实验截图:

技术图片

2.实验任务2

实验代码:

 1 assume cs:code, ds:data
 2 data segment
 3     str db try, 0
 4 data ends
 5 
 6 code segment
 7 start:  
 8     mov ax, data
 9     mov ds, ax
10 
11     mov si, offset str
12     mov al, 2
13     call 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
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

实验截图:

技术图片

 修改后截图:

技术图片

 回答问题:

(1)line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?

答:通过栈保存子程序中会遇到的寄存器的值,防止子程序中修改了相应寄存器的值之后,原来的值无法恢复。

(2)line30的功能是什么?

答:将cx中的值赋值给es:[di]。其中cx中的数据代表字符和它的属性,es:[di]代表显存的对应位置,赋值后可以在屏幕上打印出来。

3.实验任务3

(1)子任务1

 1 assume cs:code, ds:data
 2 data segment
 3         x dw 1984
 4         str db 16 dup(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

调试截图:

技术图片

 

 

技术图片

技术图片

技术图片

(2)子任务2

实验代码:

 1 assume cs:code, ds:data
 2 data segment
 3         x dw 1984
 4         str db 16 dup(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 si, offset str
16         mov al, 2
17         call printStr
18 
19         mov ah, 4ch
20         int 21h
21 
22 num2str:
23         push ax
24         push bx
25         push cx
26         push dx
27 
28         mov cx, 0
29         mov bl, 10
30 s1:
31         div bl
32         inc cx
33         mov dl, ah
34         push dx
35         mov ah, 0
36         cmp al, 0
37         jne s1
38 s2:
39         pop dx
40         or dl, 30h
41         mov [di], dl
42         inc di
43         loop s2
44 
45         pop dx
46         pop cx
47         pop bx
48         pop ax
49 
50         ret
51 
52 printStr:
53         push bx
54         push cx
55         push si
56         push di
57 
58         mov bx, 0B800H
59         mov es, bx
60         mov di, 0
61 s:      mov cl, [si]
62         mov ch, 0
63         jcxz over
64         mov ch, al
65         mov es:[di], cx
66         inc si
67         add di, 2
68         jmp s
69 
70 over:   pop di
71         pop si
72         pop cx
73         pop bx
74 
75         pop ax
76         jmp ax
77 
78 code ends
79 end start

实验截图:

技术图片

 改变数字:

技术图片

4.实验任务4

实验代码:

 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

实验截图:

技术图片

回答问题:

(1)line12-19实现的功能是:循环读入字符,当遇到#的时候停止读入,跳转到next段执行子程序。

(2)line21-27实现的功能是:将之前输入的内容输出到屏幕上。

5.实验任务5

 1 #include <stdio.h>
 2 int sum(int, int);
 3 
 4 int main() {
 5 00771760  push        ebp  
 6 00771761  mov         ebp,esp  
 7 00771763  sub         esp,0E4h  
 8 00771769  push        ebx  
 9 0077176A  push        esi  
10 0077176B  push        edi  
11 0077176C  lea         edi,[ebp-0E4h]  
12 00771772  mov         ecx,39h  
13 00771777  mov         eax,0CCCCCCCCh  
14 0077177C  rep stos    dword ptr es:[edi]  
15 0077177E  mov         ecx,offset _45D01272_源@cpp (077C003h)  
16 00771783  call        @__CheckForDebuggerJustMyCode@4 (0771208h)  
17     int a = 2, b = 7, c;
18 00771788  mov         dword ptr [a],2  
19 0077178F  mov         dword ptr [b],7  
20 
21     c = sum(a, b);
22 00771796  mov         eax,dword ptr [b]  
23 00771799  push        eax  
24 0077179A  mov         ecx,dword ptr [a]  
25 0077179D  push        ecx  
26 0077179E  call        sum (077107Dh)  
27 007717A3  add         esp,8  
28 007717A6  mov         dword ptr [c],eax  
29 
30     return 0;
31 007717A9  xor         eax,eax  
32 }

 

 1 int sum(int x, int y) {
 2 007716F0  push        ebp  
 3 007716F1  mov         ebp,esp  
 4 007716F3  sub         esp,0C0h  
 5 007716F9  push        ebx  
 6 007716FA  push        esi  
 7 007716FB  push        edi  
 8 007716FC  lea         edi,[ebp-0C0h]  
 9 00771702  mov         ecx,30h  
10 00771707  mov         eax,0CCCCCCCCh  
11 0077170C  rep stos    dword ptr es:[edi]  
12 0077170E  mov         ecx,offset _45D01272_源@cpp (077C003h)  
13 00771713  call        @__CheckForDebuggerJustMyCode@4 (0771208h)  
14     return (x + y);
15 00771718  mov         eax,dword ptr [x]  
16 0077171B  add         eax,dword ptr [y]  
17 }
18 0077171E  pop         edi  
19 0077171F  pop         esi  
20 }
21 00771720  pop         ebx  
22 00771721  add         esp,0C0h  
23 00771727  cmp         ebp,esp  
24 00771729  call        __RTC_CheckEsp (0771212h)  
25 0077172E  mov         esp,ebp  
26 00771730  pop         ebp  
27 00771731  ret  

 

(1)高级语言中形参列表是从右向左进行入栈的,先将数据存入寄存器中,再进行入栈操作。

(2)调用函数后返回是调用call命令和ret命令进行的。 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!