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

四、实验结论

1. 实验任务1

源程序:

assume cs:code, ds:data
data segment
    str db 'welcome to masm!'
data ends

code segment
start: 
    mov ax,0b800h;目标段地址
    mov ds,ax    
    mov bx,data;源段地址
    mov es,bx

    mov cx,16
    mov di,0
    mov si,0720h;屏幕中间的位置的偏移地址

s:    jcxz sss;如果cx为零跳转下一个循环
    mov ax,es:[di]
    mov ds:[si],ax;将当前的字符复制给目标位置
    mov byte ptr ds:[si+1],02h;给当前字符添加颜色属性
    add si,2
    inc di
    loop s

sss:    mov cx,16
    mov di,0
    mov si,07c0h

s1:    jcxz ss1
    mov ax,es:[di]
    mov ds:[si],ax
    mov byte ptr ds:[si+1],24h
    add si,2
    inc di
    loop s1

ss1:    mov cx,16
    mov di,0
    mov si,0860h

s2:    jcxz ss2
    mov ax,es:[di]
    mov ds:[si],ax
    mov byte ptr ds:[si+1],71h
    add si,2
    inc di
    loop s2

ss2:    mov ah,4ch
    int 21h

code ends
end start

我实现该任务是是用了暴力的三次循环来完成对屏幕显示区域地址的赋值操作,即每次更改当前目标的偏移地址,相应的赋值 操作也可用ASCII码来完成。

运行结果截图

 

 

 2. 实验任务2

源程序:

assume cs:code, ds:data
data segment
    str db 'another try', 0
data ends

code segment
start:  
    mov ax, data
    mov ds, ax

    mov si, offset str
    mov al, 4
    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

运行结果截图

 

 修改后运行结果截图

 

 

1) 目的是为了事先将寄存器入栈,在接下来的程序结束后将已经更改过的寄存器的值恢复到原来的值,这样便可以起到保护现场的作用。

2) 将数据段的当前字符复制到屏幕显示的目标地址中。

3. 实验任务3

子任务1

反汇编截图

 

 子任务二

源代码

assume cs:code, ds:data
data segment
        x dw 1234
        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,4
        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. 实验任务4

源代码

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

运行测试截图

 

 

1) 利用int 21h的一号子功能,将从键盘输入的字符保存到data段中,当判断输入为‘#’时,跳转到next段中,否则继续输入保存。

2) 将s1段中用于保存数据偏移地址的si寄存器作为循环次数,利用int 21h的2号子功能在屏幕上依次将输入的数据输出出来。

5.实验任务5

#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);
}

 

 

 

 

通过观察分析可知,当进行函数调用的时候,对参数进行按自右向左的顺序,先存在寄存器中,利用寄存器进行入栈操作,然后通过call命令调用函数进入函数内部。在函数内部,执行具体的加法操作,将形参存储在寄存器中然后进行相关运算,最后通过ret指令返回。返回到主程序后将暂存运算结果的寄存器的值赋值给存储c变量的寄存器即完成了一次完整的函数调用。

 五、实验总结

1.通过本次实验我了解并掌握了如何对屏幕显示区域进行赋值操作,并使得显示的字符属性按相应的要求设置。

2.学到了防止多次使用的寄存器在程序执行过程中被修改可以事先放入栈中保存。

3.熟悉了各种跳转指令的跳转原理和使用。

4.学到了int 21h的多个子功能。

5.通过对高级语言程序的反汇编进一步了解了高级语言函数的调用在汇编语言下是如何完成的,使我对高级语言的执行有了更深入的了解。

posted @ 2020-12-12 15:03  有女孩说要娶我  阅读(134)  评论(2)    收藏  举报