实验4 汇编应用编程和C语言程序反汇编分析
实验任务1
task4-1.asm:
assume cs:code,ds:data data segment db 'welcome to masm!' db 02h,24h,71h ;三种颜色对应的16进制代码 data ends code segment start: mov ax,data mov ds,ax mov ax,0b800h mov es,ax ;设置显存段地址 mov di,1824 ;附加段数据的偏移地址 mov bx,16 ;获取颜色的偏移地址 mov cx,3 ;设置循环次数为3 s0: mov dx,cx ;将外层循环的cx值保存在dx中 mov si,0 ;设置段数据的偏移地址 mov cx,16 ;设置内层循环次数为16 s: mov al,[si] ;获取字符数据 mov ah,[bx] ;获取颜色数据 mov es:[di],ax ;将彩色字符数据写入显存 add di,2 ;附加段偏移地址增加2,便于下一个彩色字符的写入 inc si ;取下一个字符数据 loop s add di,128 ;写入下一行 inc bx ;取另一种颜色属性 mov cx,dx ;用dx存放的外层循环的计数值恢复cx loop s0 ;外层循环的loop指令将cx中的计数值减1 mov ax,4c00h int 21h code ends end start
运行结果:

实验任务2
task4-2.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
运行结果:

对源程序进行以下修改后:
把line3改为:
str db 'another try',0
把line12改为:
mov al,4
运行结果:

- line19-22,line36-39,这组对称使用的push、pop,这样用的目的是什么?
这组对称使用的push、pop是为了防止在进行修改后出现问题却又无法回到原始位置。
- line30的功能是什么?
line30的功能是将彩色字符存入显存中。
实验任务3
task4-3.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命令进行反汇编:


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

使用d命令查看数据段内容:

完善后的task4-3.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 si,offset str mov al,2 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
运行结果:

把line3中的整数改成0-2559之间的任意数,运行结果:

实验任务4
task4-4.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
运行结果:

- line12-19实现的功能是?
line12-19实现的功能是接收输入的字符串,知道输入一个“#”表示输入结束。
- line21-27实现的功能是?
line21-27实现的功能是将之前输入的字符串显示到屏幕上。
实验任务5
在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分别设置断点:

反汇编:
#include<stdio.h> int sum(int,int); int main(){ 003913B0 push ebp 003913B1 mov ebp,esp 003913B3 sub esp,0E4h 003913B9 push ebx 003913BA push esi 003913BB push edi 003913BC lea edi,[ebp-0E4h] 003913C2 mov ecx,39h 003913C7 mov eax,0CCCCCCCCh 003913CC rep stos dword ptr es:[edi] int a=2,b=7,c; 003913CE mov dword ptr [a],2 003913D5 mov dword ptr [b],7 c=sum(a,b); 003913DC mov eax,dword ptr [b] 003913DF push eax 003913E0 mov ecx,dword ptr [a] 003913E3 push ecx 003913E4 call sum (39105Ah) 003913E9 add esp,8 003913EC mov dword ptr [c],eax return 0; 003913EF xor eax,eax } 003913F1 pop edi 003913F2 pop esi 003913F3 pop ebx 003913F4 add esp,0E4h 003913FA cmp ebp,esp 003913FC call @ILT+305(__RTC_CheckEsp) (391136h) 00391401 mov esp,ebp 00391403 pop ebp 00391404 ret
int sum(int x,int y){ 00391420 push ebp 00391421 mov ebp,esp 00391423 sub esp,0C0h 00391429 push ebx 0039142A push esi 0039142B push edi 0039142C lea edi,[ebp-0C0h] 00391432 mov ecx,30h 00391437 mov eax,0CCCCCCCCh 0039143C rep stos dword ptr es:[edi] return (x+y); 0039143E mov eax,dword ptr [x] 00391441 add eax,dword ptr [y] } 00391444 pop edi 00391445 pop esi 00391446 pop ebx 00391447 mov esp,ebp 00391449 pop ebp 0039144A ret
总结:
从汇编角度看,高级语言中参数传递是通过栈实现的,即将参数入栈保存到内存单元中,然后使用寄存器来使参数出栈调用;返回值是存入到eax中实现。参数的入栈顺序是后定义的数据先入栈。

浙公网安备 33010602011771号