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

四、实验结论

1. 实验任务1

附上源程序代码

 1 ; task1.asm
 2 assume cs:code, ds:data
 3 data segment
 4     db 'welcome to masm!', 0
 5     color db 2, 24h, 71h    ; store color attributes here
 6 data ends
 7 code segment
 8 start:
 9     mov ax, data
10     mov ds, ax
11     mov bx, 720h        ; 11(line)*160(bytes/line)+32(column)*2(bytes/column)
12     mov cx, 3            ; loop 3 times for 3 lines
13     mov di, 0            ; offset of color attributes in color segment
14     mov si, 0
15 
16 s:  mov ah, color[di]        ; store color attribute in ah, and character in al
17     call print            ; print the string at position es:[bx+si]
18     add bx, 0a0h        ; switch to next line (+160bytes)
19     inc di            ; switch to next color attribute
20     loop s
21 
22     mov ah, 4ch
23     int 21h
24 
25 print:
26     push es            ; push registers so that they can be used in subprogram
27     push dx
28     push di
29     push si
30     push ax
31     mov dx, 0b800h        ; video memory
32     mov es, dx
33     mov di, 0
34 
35 sprint:    mov al, ds:[si]        ; store color attribute in ah, and character in al
36     cmp al, 0            ; if string ends, then return
37     je ed
38     mov es:[bx+di], ax    ; print the character
39     inc si
40     add di, 2
41     jmp sprint
42 
43 ed: pop ax
44     pop si
45     pop di
46     pop dx
47     pop es
48     ret
49 
50 code ends
51 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

附上运行结果截图

修改Line3与Line12后运行结果截图:

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

在子程序执行之前将寄存器的数据保存至栈中,子程序执行结束返回之前再将寄存器的数据从栈中恢复,可以保护主程序在栈中存放的数据不被修改。

line30的功能是什么?

将要显示的数据移动至显存区域,以在屏幕上显示。

3. 实验任务3

附上子任务1的反汇编截图

程序运行前首先查看内存,再反汇编

可以看出此时内存中数据为0,程序结束前的指令地址为076c:000e。使用g命令执行至程序结束前

可以看出1984被成功存放在数据段中str标号后面的单元。

附上子任务2修改、完善后的完整汇编源代码,及,运行测试截图

将task2.asm中的printStr添加至task3.asm后

 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, 70h
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     ret
75 code ends
76 end start

运行结果:

4. 实验任务4

附上程序源代码

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

附上运行测试截图

line13-20实现的功能是?

从键盘中读取字符存入data segment中,直到遇到'#'结束。

line22-28实现的功能是?

将用户输入的串在屏幕上打印。

5. 实验任务5

 1 // task5.c
 2 #include <stdio.h>
 3 
 4 int sum(int, int);
 5 
 6 int main() {
 7     int a = 2, b = 7, c;
 8     c = sum(a, b);
 9     return 0;
10 }
11 
12 int sum(int x, int y) {
13     return (x + y);
14 }

由于我的电脑上未安装Visual Studio环境,下面使用gcc环境进行反汇编等操作。使用gcc命令进行编译得到task5.o文件,然后使用objdump命令进行反汇编。

(base) PS D:\> gcc -g -c task5.c
(base) PS D:\> objdump -d -M intel -S task5.o >> task5.s

使用这种方式得到的.s文件同时包含.c文件源代码以及反汇编指令代码,阅读起来较为方便,使用以下命令同样也可以进行反汇编,但是得到的.s文件仅有反汇编指令代码。

gcc -S task5.c

查看task5.s中的内容

 1 task5.o:     file format pe-i386
 2 
 3 
 4 Disassembly of section .text:
 5 
 6 00000000 <_main>:
 7 // task5.c
 8 #include <stdio.h>
 9 
10 int sum(int, int);
11 
12 int main() {
13    0:    55                       push   ebp
14    1:    89 e5                    mov    ebp,esp
15    3:    83 e4 f0                 and    esp,0xfffffff0
16    6:    83 ec 20                 sub    esp,0x20
17    9:    e8 00 00 00 00           call   e <_main+0xe>
18     int a = 2, b = 7, c;
19    e:    c7 44 24 1c 02 00 00     mov    DWORD PTR [esp+0x1c],0x2
20   15:    00 
21   16:    c7 44 24 18 07 00 00     mov    DWORD PTR [esp+0x18],0x7
22   1d:    00 
23     c = sum(a, b);
24   1e:    8b 44 24 18              mov    eax,DWORD PTR [esp+0x18]
25   22:    89 44 24 04              mov    DWORD PTR [esp+0x4],eax
26   26:    8b 44 24 1c              mov    eax,DWORD PTR [esp+0x1c]
27   2a:    89 04 24                 mov    DWORD PTR [esp],eax
28   2d:    e8 0b 00 00 00           call   3d <_sum>
29   32:    89 44 24 14              mov    DWORD PTR [esp+0x14],eax
30     return 0;
31   36:    b8 00 00 00 00           mov    eax,0x0
32 }
33   3b:    c9                       leave  
34   3c:    c3                       ret    
35 
36 0000003d <_sum>:
37 
38 int sum(int x, int y) {
39   3d:    55                       push   ebp
40   3e:    89 e5                    mov    ebp,esp
41     return (x + y);
42   40:    8b 55 08                 mov    edx,DWORD PTR [ebp+0x8]
43   43:    8b 45 0c                 mov    eax,DWORD PTR [ebp+0xc]
44   46:    01 d0                    add    eax,edx
45   48:    5d                       pop    ebp
46   49:    c3                       ret    
47   4a:    90                       nop
48   4b:    90                       nop
  • 参数传递:Line24-27可以看出在调用sum子函数前,main函数将两个参数放在了栈顶上方,即[esp][esp+0x4],在sum子函数里,再从[esp+0x8][esp+0xc]处取得。这里猜测是调用sum函数时,将CS与EIP压入了栈中,所以ESP减小了0x8
  • 返回值传递:Line29与Line44可以看出返回值存放在EAX寄存器中。
  • 参数顺序:比较Line19-21与Line24-27可以看出,在调用c=sum(a, b)时,b首先被存至栈顶上方一个int处,接着a再被存至栈顶处。所以参数的处理顺序为从右至左。
posted @ 2020-12-12 22:13  xywei0905  阅读(289)  评论(2)    收藏  举报