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

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

assume cs:code, ds:data, ss:stack
data segment
    db 'welcome to masm!'                       
    db 02H, 0A4H, 71H, 0000000000000    
    dw 12*160+6413*160+6414*160+6400000
data ends
stack segment         
    dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:
    mov ax, stack     
    mov ss, ax      
    mov sp, 16
mov ax, data      
mov ds, ax
mov ax, 0B800H      
mov es, ax
mov cx, 3       
mov bx, 16      
mov di, 32      
s0:  push cx            
    mov cx, 16    
    mov bp, [di]       
    mov si, 0

s1: 
    mov al, [si]        
    mov ah, [bx]       
    mov es:[bp], ax
inc bp
inc bp          
inc si          
loop s1
pop cx
add bx, 1       
add di, 2      
loop s0
mov ax,4c00H
int 21H
code ends
end start

 根据已学知识,分别设置数据段保存字符的ASCII值,字符的位置,和背景及颜色的控制。根据前几次实验的经验,取8个字节的空间作为栈空间以实现循环。

通过嵌套循环实现对显存区域的输送。

根据要求计算送入区域应该为第12行,13行,14行,列偏移位置应该为160/2-16(字符串一共16个字节),所以偏移地址为: 12*160+64, 13*160+64, 14*160+64

实际效果如下:

根据提示:doSbox显示窗口是80×25彩色字符模式显示,重复三次显示'welcom to masm!'需要将数据存入的现存地址为:

      十二行中心区域:b800:0720~b800:0740(32个字节(十六个字符十六个颜色))

                     十三行中心区域:b800:07C0~b800:07E0

                     十四行中心区域:b800:0860~b800:0880

     使用debug,在使用g指令执行完程序后查看对应地址的数据:(虚拟机中win7系统的cmd命令窗口)

 2. 实验任务2

编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。

  编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。
  子程序printSar
         功能:以指定颜色在屏幕上(从屏幕左上角开始)输出字符串
  要求:字符串以0结尾
  入口参数
  字符串的起始地址—> ds: si (其中,字符串所在段的段地址—> ds, 字符串起始地址的偏移地址—> si,字符串颜色—> al

  出口参数:无

  使用任意文本编辑器,录入汇编程序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

汇编、运行程序,观察运行结果。

 对源程序做如下修改:

    把line3改为:

str 1 db 'another try', 0

把line12改为:

mov al, 4

基于运行结果,理解源代码,以及,组合使用转移指令call和ret实现子程序的原理与方法。具体地,在line18-40中:
line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?line31的功能是什么?

  ine19-22中使用push将寄存器的值压入栈中,目的是保存程序跳转前的状态;

  line36-39,使用pop指令对数据进行出栈操作,目的是回到程序跳转前的状态;

  line31:mov  es:[di] ,cx作用是将取出的data段中的字符数据以及该字符显示的颜色数据存入显存地址中。

     实验代码中用cl存储data段中取出的数据,ch先置为0,经过jcxz指令通过后在将控制颜色的数据传给ch;

       当cl还未取到data数据段的最后一个数据时,cx的值就不为零,在将控制颜色的数据传给ch,然后将cx的数据存入显存地址段中。

       当cl取到data数据段的末尾时(最后一个数据为0),在执行jcxz指令时cx为0 ,跳转(同时说明数据取完)。

3. 实验任务3
  使用任意文本编辑器,录入汇编源程序task3.asm。
  子程序num2str:
         功能:把0~2559之间的任意整数转换成数字字符串,例如,把1984转换成'1984'
     入口参数
       要转换的整数 —> ax
       数字字符串的起始地址 —> ds:di (其中:数字字符串所在段的段地址—> ds,字符串起始地址的偏移地址—>di)
     出口参数:无 1 assume cs:code, ds:data 2 data segment

assume cs:code, ds:data
data segment
        x dw 1984
        str1 db 16 dup(0)
data ends

code segment
start:
        mov ax, data
        mov ds, ax
        mov ax, x
        mov di, offset str1
        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           

        mov ax,0b800h
        mov es,ax
        mov si,0
        mov ah,2h
s2:
        pop dx           
        or dl, 30h        
        mov [di], dl    
        mov es:[si],dl
        mov es:[si+1],ah
        add si,2h
        inc di
        loop s2

        pop dx
        pop cx
        pop bx
        pop ax

        ret
code ends
end start

阅读源代码,理解子程序num2str的汇编实现。
子任务1
  对task3.asm进行汇编、链接,得到可执行程序后,在debug中使用u命令反汇编,使用g命令执行
  到line15(程序退出之前),使用d命令查看数据段内容,观察是否把转换后的数字字符串'1984'存放
  在数据段中str标号后面的单元。
子任务2
  对task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来,
  实现对转换后的字符串进行输出。
  预期输入结果如下:

把task3.asm源代码中,line3中整数改成0~2559之间的任意数值,运行测试,观察结果。

 任务1:

对task3.asm进行汇编、链接,得到可执行程序后,在debug中对程序进行调试:

1、使用u命令反汇编:

2、使用g命令执行到line15(程序退出之前),使用d命令查看数据段内容, 

 子任务2
对task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来,实现对转换后的字符串进行输出。
在代码中增加line35~38,line43~45,将拆分出来的数字显示在窗口上,如图:

将line3中的整数改为2000,编译连接后运行结果如图:

 将line3中的整数改为199,编译连接后运行结果如图:

 

 4. 实验任务4
使用任意文本编辑器,录入汇编源程序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

汇编、链接、运行程序,输入一个字符串并以#结束(比如,2020, bye#)观察运行结果。
结合运行结果,理解程序功能,了解软中断指令。具体地:
line12-19实现的功能是?
line21-27实现的功能是?

编译连接后运行结果如图:输入字符串为2020,bye#

 输入结束符号#后程序立即输出出入的字符串(除#)

   line12-19实现的功能是:使用int 21h的1号子功能从键盘中输入字符,保存到data数据段中,输入的字符以#结尾(#不存入,也不做输出)。

   line21-27实现的功能是:使用int 21h的2号子功能将存入data数据段中的字符在屏幕上输出。

5. 实验任务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分别设置断点,在调试模式下,查看反汇编代码。

 

 

 

 

分析反汇编代码,从汇编的角度,观察高级语言中参数传递和返回值是通过什么实现的,以及,参数入栈顺序,返回值的带回方式。

结合查询资料:

在主函数main内,先进行初始化操作,将默认堆栈寄存器压入栈。然后进行变量声明,若变量有初值,则反汇编就会为其生成一条 Mov指令为其赋值,对于没有初值的变量其每个字节都为0xCCH。

调用函数时,形参参数入栈自右向左。先借助寄存器,将参数b 的地址压入堆栈寄存器eax,再将参数a 的值压入堆栈寄存器ecx。实现了实参赋值给形参,通过 call 指令调用函数sum。

sum函数内同样先初始化并分配栈空间,执行得到的结果保存在eax寄存器内,调用ret指令返回。

执行完毕,返回主函数main,再将eax值赋值给参数c。主调函数根据压入堆栈的参数的数目 2 和参数大小,利用指令 add ESP,8 将参数全部弹出。此时堆栈就恢复到其调用前的状态。

五、实验总结 

(1)复习了利用显存区域打印输出

(2)学习了利用int 21h 的子功能输入和输出

  (3)通过反汇编观察高级语言函数调用,可以发现形参变量最终不被保存在堆栈中,所以在函数内改变形参不会改变主函数实参的值。

 

posted @ 2020-12-15 20:01  Mayenne-白姬  阅读(258)  评论(1编辑  收藏  举报