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

实验结论

1. 实验任务1

编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcome to masm!'。
源程序:
 
DATAS SEGMENT
     db 'welcome to masm!';    ;闪烁1+背景3+高亮1+前景颜色3(RGB) 
     db 00000010B              ;黑底绿字
     db 00100100B              ;绿底红字
     db 01110001B              ;白底蓝字
DATAS ENDS

STACKS SEGMENT
     db 16 dup(0)                ;多次嵌套循环,储存cx
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX                    ;ds指向字符串
    ;此处输入代码段代码
    mov ax, 0b800H             ;指初始缓存
    mov es, ax
    
    mov ax, stacks               ;指栈
    mov ss, ax 
    mov sp, 10h                   ;指栈顶
    

    mov cx, 3                      ;设置外围循环次数,共三行
    mov bx, 16                    ;颜色数据的初始偏移地址
    mov di, 720h                 ; 初始化 di显存
    
s:  push cx 
    
    mov cx, 16                    ;内循环16次,16个字符
    mov si, 0                       ;初始化 si

s0: mov al, ds:[si]              ;取数据段内对应字符
    mov ah,ds:[bx]
    ;mov es:[bx+si],al            ;  低位存放字符
    ;mov es:[bx+si+1],ah       ; 高位存放颜色
    mov es:[di],ax                 ;写入显存
    inc si                                ; si + 1,移向数据段下一字符
    add di, 2                          ; di + 2,移向显存下一个字
   
    loop s0;
    
    pop cx
    add di,080h        ;实现换行0a0h -32
    inc bx                 ;bx改变一个字节
    loop s
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

程序结果:

 

 

2. 实验任务2

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

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中:
Q1: line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?
A1:多次循环,替父程序保存寄存器的值,使子程序的执行更加便捷。
 
Q2:line30的功能是什么?
A2:将字符和对应的颜色信息存储到显存中。
 

 3. 实验任务3

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

子任务1:

对task3.asm进行汇编、链接,得到可执行程序后,在debug中使用u命令反汇编,使用g命令执行
到line15(程序退出之前),使用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

 

 

 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#)观察运行结果。结合运行结果,理解程序功能,了解软中断指令。

Q:line12-19实现的功能是?
A:   从键盘中输入字符串,直到遇到#停止。
Q:line21-27实现的功能是?
A:   将数据段中的字符显示输出。
 
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设置断点,调试模式下查看反汇编代码:

 
分析反汇编代码,从汇编的角度,观察高级语言中参数传递和返回值是通过什么实现的,以及,参数入
栈顺序,返回值的带回方式,等等。
 
高级语言中参数传递,从汇编的角度是如何传递的:高级语言中参数传递和返回值是通过栈实现的
多个参数的入栈顺序:先将参数b入栈,再将参数a入栈。
函数调用栈:
调用函数时,形参参数入栈自右向左。先借助寄存器,将参数b 的地址压入堆栈寄存器eax,再将参数a 的值压入堆栈寄存器ecx。
用call命令调用sum函数,最后返回真正的值为eax,再传入双字数据ptr[c],函数的返回值放在eax寄存器中,调用ret指令返回。
posted @ 2020-12-17 20:50  浔川Dawn  阅读(204)  评论(2)    收藏  举报