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

实验内容

实验任务 1

在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串‘welcome to masm!’。

task1.asm:

assume cs:code, ds:data, ss:stack

data segment
    db 'Welcome to masm!'           ;16个字节
    db 02H, 0A4H, 71H, 0, 0, 0, 0, 0    ;8个字节
    dw 1824, 1984, 2144, 0, 0, 0, 0, 0  ;8个字
data ends

stack segment
    dw 0, 0, 0, 0, 0, 0, 0, 0       ;用于存放cx
stack ends

code segment
start:
    mov ax, data            ;数据段
    mov ds, ax
    mov ax, stack               ;栈
    mov ss, ax
    mov sp, 16
    mov ax, 0B800H              ;显存
    mov es, ax
    
    mov cx, 3               ;s0 运行三次,共 3 行
    mov bx, 16              ;data 中颜色段起始地址
    mov di, 24              ;data 中地址段存储地址

s0:    push cx                 ;用栈暂存外部 cx
    mov cx, 16              ;16 个字母
    mov bp, ds:[di]             ;设置显存起始地址
    mov si, 0               ;设置句子起始地址

s1:    mov al, ds:[si]             ;设置字型
    mov ah, ds:[bx]             ;设置颜色
    mov es:[bp], ax             ;写入显存
    add bp, 2               ;移动
    inc si
    loop s1

    pop cx                  ;取回外部 cx
    add bx, 1               ;移到下一个颜色
    add di, 2               ;移到显存下一个起始地址    
    loop s0

    mov ax, 4c00H
    int 21H
code ends
end start

运行结果:

实验任务 2

编写子程序 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

运行结果:

把 line3 改为:

str db 'another try', 0

把 line12 改为:

mov al, 4

运行结果:

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

  • line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?
    在本程序中,存在子程序的调用,在子程序调用前,需要把子程序中使用到的各寄存器的值放入栈内存储,防止被覆盖。在返回父程序后,再将站内的值取出返回各寄存器,即可继续父程序的运行
  • line30 的功能是什么
    ds:[si]内的值为字符,将其放入 cl,ch 值设为 0,此时若 cx 寄存器内的值为 0,说明已经完成了字符串的输出,即可终止当前子程序,进入 over。

实验任务 3

task3.asm

子任务 1:
对 task3.asm 进行汇编、链接,得到可执行程序后,在 debug 中使用 u 命令反汇编,使用 g 命令执行到 line 15(程序退出之前),使用 d 命令查看数据段内容,观察是否把转换后的字符串 ‘1984’ 存放到在数据段中 str 标号后面的单元。

成功

子任务 2:
对 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

运行结果:

把 task3.asm,line3 中整数换成0~2559之中任意数值,运行测试,观察结果:


颜色与背景色与 al 相关,ax = x

实验任务 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

运行结果:

  • line12-19 实现的功能:
    读入字符直到 # 为止

  • 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 分别设置断点,在调试模式下,查看反汇编代码:


在函数调用处,将[b],[a]对应的值移给 eax 与 ecx 寄存器,然后将两个寄存器中的值存入栈内,参数入栈约定为自右向左,然后通过 call 跳转到对应的 sum 函数处。
sum 函数完成后,将 eax 寄存器内的值传给 [c],函数完成。


sum 函数中,通过 [x] 直接获取值并将其移入 eax,将 [y] 对应的值加给 eax,通过 eax 实现返回值,完成加法运算。一系列操作后 ret,回到主程序。

实验结论

分享:C语言函数调用反汇编内容详细可见:https://blog.csdn.net/songjinshi/article/details/8450419

posted @ 2020-12-11 22:32  maranlll  阅读(98)  评论(2)    收藏  举报