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

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

一、实验目的

1. 理解80×25彩色字符模式显示原理
2. 理解转移指令jmp, loop, jcxz的跳转原理,掌握使用其实现分支和循环的用法
3. 理解转移指令call, ret, retf的跳转原理,掌握组合使用callret/retf编写汇编子程序的方法,掌握参数传递方式
4. 理解标志寄存器的作用
5. 理解条件转移指令je, jz, ja, jb, jg, jl等的跳转原理,掌握组合使用汇编指令cmp和条件转移指令实现分支和循环的用法
6. 了解在visual studio/Xcode等环境或利用gcc命令行参数反汇编c语言程序的方法,理解编译器生成的反汇编代码
7. 综合应用寻址方式和汇编指令完成应用编程

二、实验内容及结果

(一)实验任务一

教材「实验9 根据材料编程」(P187-189)
编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcome to masm!'
。 
源代码如下:

assume cs:code

data segment

db 'welcome to masm!' ;要显示的内容

data ends

code segment

start: ;设置数据段地址

mov ax,data

mov ds,ax

mov ax,0B800H ;B800H显示缓冲区的起始地址

mov es,ax

mov bx,0 ;字符串内容的偏移地址,每次增加1

mov bp,64 ;缓冲区的偏移地址,每次增加2

mov cx,16 ;循环16次

a: mov al,ds:[bx] ;取得字符串的字节数据

mov ah,02H ;黑底绿色

mov es:[bp+6E0H],ax ;(垂直居中)显示在第11行上

mov ah,24H ;绿底红色

mov es:[bp+780H],ax ;(垂直居中)显示在第12行上

mov ah,71H ;白底蓝色

mov es:[bp+820H],ax ;(垂直居中)显示在第13行上

inc bx ;累加操作

add bp,2

loop a

mov ax,4C00H

int 21H

code ends

end start

使用masmlink对exp9.asm进行汇编、链接,得到可执行文件exp9.exe,运行并观察结果。

1、具体的汇编、链接过程可以参考《汇编语言程序设计 实验2 汇编源程序编写与汇编、调试》。运行exp9.exe文件,得到结果:

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

(二)实验任务二

编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。
使用任意文本编辑器,录入汇编源程序task2.asm,源代码如下:

assume cs:code, ds:data

data segment

str db 'try', 0

data ends

code segment

start:

mov ax, data

mov ds, ax

mov si, offset str

mov al, 2

call printStr

mov ah, 4ch

int 21h

printStr:

push bx

push cx

push si

push di

mov bx, 0b800H

mov es, bx

mov di, 0

s: mov cl, [si]

mov ch, 0

jcxz over

mov ch, al

mov es:[di], cx

inc si

add di, 2

jmp s

over: pop di

pop si

pop cx

pop bx

ret

code ends

end start

使用masmlink对task2.asm进行汇编、链接,得到可执行文件task2.exe,运行结果如下所示:

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

 对源程序做如下修改:
line3改为:


str db 'another try', 0

修改后的结果如下所示:

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

line12改为:  

mov al, 4

修改后的结果如下所示:

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

 可以得知:mov al改变了字符的颜色属性

 基于运行结果,理解源代码,以及,组合使用转移指令callret实现子程序的原理与方法。具体地,在line18-40中:

line19-22, line36-39,这组对称使用的pushpop,这样用的目的是:利于恢复各寄存器的值。 

line30的功能是:通过“mov es:[di], cx”可以读取目标数据存入es。

(三)实验任务三

使用任意文本编辑器,录入汇编源程序task3.asm,源代码如下所示:

assume cs:code, ds:data

data segment

x dw 1984

str db 16 dup(0)

data ends

code segment

start:

mov ax, data

mov ds, ax

mov ax, x

mov di, offset str

call num2str

mov ah, 4ch

int 21h

num2str:

push ax

push bx

push cx

push dx

mov cx, 0

mov bl, 10

s1:

div bl

inc cx

mov dl, ah

push dx

mov ah, 0

cmp al, 0

jne s1

s2:

pop dx

or dl, 30h

mov [di], dl

inc di

loop s2

pop dx

pop cx

pop bx

pop ax

ret

code ends

end start

首先使用u命令对task.exe进行反汇编,结果如下所示:

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

 使用g命令执行到line15(程序退出之前)

-g 0e

 使用d命令查看数据段内容 ,结果如下所示:

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

task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来,实现对转换后的字符串进行输出。  源代码如下所示:

assume cs:code, ds:data

data segment

x dw 1984

str db 16 dup(0)

data ends

code segment

start:

mov ax, data

mov ds, ax

mov ax, x

mov di, offset str

call num2str

mov si, offset str

call printStr

mov ah, 4ch

int 21h

num2str:

push ax

push bx

push cx

push dx

mov cx, 0

mov bl, 10

s1:

div bl

inc cx

mov dl, ah

push dx

mov ah, 0

cmp al, 0

jne s1

s2:

pop dx

or dl, 30h

mov [di], dl

inc di

loop s2

pop dx

pop cx

pop bx

pop ax

ret

printStr:

push bx

push cx

push si

push di

mov bx, 0b800H

mov es, bx

mov di, 0

s:

mov cl, [si]

mov ch, 0

jcxz over

mov ch, al

mov es:[di], cx

inc si

add di, 2

jmp s

over: pop di

pop si

pop cx

pop bx

ret

code ends

end start

结果如下所示:

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

task3.asm源代码中,line3中整数改成0~2559之间的任意数值,运行测试,结果如下所示:

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

(四)实验任务四

使用任意文本编辑器,录入汇编源程序task4.asm,源代码如下所示:

assume cs:code, ds:data

data segment

str db 80 dup(?)

data ends

code segment

start:

mov ax, data

mov ds, ax

mov si, 0

s1:

mov ah, 1

int 21h

mov [si], al

cmp al, '#'

je next

inc si

jmp s1

next:

mov cx, si

mov si, 0

s2: mov ah, 2

mov dl, [si]

int 21h

inc si

loop s2

mov ah, 4ch

int 21h

code ends

end start

运行结果如下所示:

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

 line12-19实现的功能是:含有中断转移指令和条件跳转指令,判断输入的字符是否为#,并将不是#的字符存入栈中

line21-27实现的功能是:含有循环指令,输出存在栈内的字符

(五)实验任务五

visual studio集成环境中,编写一个简单的包含有函数调用的c程序。代码如下: 

#include <stdio.h>

int sum(int, int);

int main() {

int a = 2, b = 7, c;

c = sum(a, b);

return 0;

}

int sum(int x, int y) {

return (x + y);

}

在line7和line13处添加断点,如图所示:

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

 在调试状态下(快捷键F5)点击“调试”->“窗口”->“反汇编”,即查看反汇编代码,结果如下:

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

结果如下所示:

int sum(int x, int y) {

00211740 push ebp

00211741 mov ebp,esp

00211743 sub esp,0C0h

00211749 push ebx

0021174A push esi

0021174B push edi

0021174C lea edi,[ebp-0C0h]

00211752 mov ecx,30h

00211757 mov eax,0CCCCCCCCh

0021175C rep stos dword ptr es:[edi]

0021175E mov ecx,offset _7FF23424_test@cpp (021C003h)

00211763 call @__CheckForDebuggerJustMyCode@4 (021130Ch)

return (x + y);

00211768 mov eax,dword ptr [x]

0021176B add eax,dword ptr [y]

}

0021176E pop edi

0021176F pop esi

00211770 pop ebx

00211771 add esp,0C0h

00211777 cmp ebp,esp

00211779 call __RTC_CheckEsp (0211235h)

0021177E mov esp,ebp

00211780 pop ebp

00211781 ret

 反汇编代码分析:(红色为c语言程序蓝色为汇编语言程序,黑色为分析)

int main() {
002117B0 push ebp   ;保存ebp,此时EBP =005BFA38,ESP = 005BFA18

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

002117B1 mov ebp,esp    ;将esp放入ebp中,此时ebp和esp相同,即执行后ESP = 005BFA18 ,EBP = 005BFA18。原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。

002117B3 sub esp,0E4h     ;把esp往上移动一个范围,等于在栈中空出一片空间来存局部变量,执行这句后ESP = 005BF934, EBP = 005BFA18,EBX = 00745000

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

002117B9 push ebx 
002117BA push esi
002117BB pushedi      ;保存三个寄存器的值
002117BC lea edi,[ebp-0E4h]       ;把ebp-oE4h加载到edi中,保存局部变量的区域
002117C2 mov ecx,39h
002117C7 mov eax,0CCCCCCCCh
002117CC rep stos dword ptr es:[edi]       ;从ebp-0E4h开始的区域初始化成全部0CCCCCCCCh,初始化局部变量空间

int a = 2, b = 7, c;

002117D8  mov         dword ptr [a],2     ;把2赋给a

002117DF  mov         dword ptr [b],7     ;把7赋给b

 c = sum(a, b);

00FD17E6 mov eax,dword ptr [b]     ;把b的值赋给eax
00FD17E9 push eax     ;eax入栈
00FD17EA mov ecx,dword ptr [a]     ;把a的值赋给ecx
00FD17ED push ecx    ;ecx入栈
00FD17EE call sum (0FD116Dh)     ;调用sum函数,可以按F11跟进
00FD17F3 add esp,8     ;调用完函数后恢复/释放栈,执行后ESP = 0079F75C,与sum函数的参数入栈前的数值一致

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

00FD17F6 mov dword ptr [c],eax     ;将结果存放在result中

return 0;
00FD17F9 xor eax,eax     ;异或后寄存器清零
}
00FD17FB pop edi     
00FD17FC pop esi
00FD17FD pop ebx     ;恢复原来寄存器的值
00FD17FE add esp,0E4h     ;恢复ESP,对应之前的sub esp,0E4h
00FD1804 cmp ebp,esp     ;检查esp是否正常,不正常就进入下边的call里面debug
00FD1806 call __RTC_CheckEsp (0FD1235h)     ;处理可能出现的堆栈异常,如果有的话,就会陷入debug
00FD180B mov esp,ebp 
00FD180D pop ebp    ;恢复原来的esp和ebp,让上一个调用函数正常使用
00FD180E ret     ;将返回地址存入eip,转移流程

以上是主函数调用的反汇编过程,以下部分是调用sum函数的过程:

int sum(int x, int y) {
00FD1740 push ebp     
00FD1741 mov ebp,esp
00FD1743 sub esp,0C0h
00FD1749 push ebx
00FD174A push esi
00FD174B push edi
00FD174C lea edi,[ebp-0C0h]
00FD1752 mov ecx,30h
00FD1757 mov eax,0CCCCCCCCh
00FD175C rep stos dword ptr es:[edi]
00FD175E mov ecx,offset _7FF23424_test@cpp (0FDC003h)
00FD1763 call @__CheckForDebuggerJustMyCode@4 (0FD130Ch)     ;与主函数的调用过程几乎相似

return (x + y);
00FD1768 mov eax,dword ptr [x]     ;取第一个参数放在eax
00FD176B add eax,dword ptr [y]     ;取第二个参数,与eax中的数值相加并存在eax中
}
00FD176E pop edi
00FD176F pop esi
00FD1770 pop ebx
00FD1771 add esp,0C0h
00FD1777 cmp ebp,esp
00FD1779 call __RTC_CheckEsp (0FD1235h)
00FD177E mov esp,ebp
00FD1780 pop ebp
00FD1781 ret     ;与主函数的调用过程几乎相似

三、实验总结

 

以上是 汇编语言程序设计 实验4 汇编应用编程和c语言程序反汇编分析 的全部内容, 来源链接: utcz.com/a/74460.html

回到顶部