三、实验内容

1.实验任务1

编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcome to masm!'。
编写程序Task_1.asm代码如下:

assume cs:code, ds:data
data segment
    db 'welcome to masm!'
    db 2h,24h,71h
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov ax,0b872h
    mov es,ax

    mov di,0
    mov ah,ds:[di+10h]
    mov al,ds:[di+11h]
    mov bh,ds:[di+12h]
    mov si,0
    mov cx,16
s:  mov bl,ds:[si]
    mov es:[di],bl
    mov es:[di+1],ah 
    mov es:[di+0a0h],bl 
    mov es:[di+0a1h],al 
    mov es:[di+140h],bl 
    mov es:[di+141h],bh 
    inc si
    add di,2
    loop s

    mov ax,4c00h
    int 21h
code ends
end start

汇编、连接之后运行Task_1.asm后,运行结果如下:

 

 其中,以下颜色对应的16进制字节:

    绿色:2h,绿底红字:24h,白底蓝字:71h

根据实验任务中所给提示,dosbox使用80*25彩色字符模式显示,一行80个字符占160个字节,因此:

b800:0720~b800:0740为第12行的中间;(32个字节(十六个字符十六个颜色))

b800:07C0~b800:07E0为第13行的中间;

b800:0860~b800:0880为第14行的中间;

每一行字符内容占用32个字节,其中16个字节是字符,16个字节是颜色。

 

2.实验任务2

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

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

对Task_2.asm进行汇编、连接,再运行生成的Task_2.exe:

  对源程序做如下修改:
  把line3改为:

str 1 db 'another try', 0

 把line12改为:

mov al, 4

再次汇编、运行程序,观察运行结果:

 

 

 问:line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?

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

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

       对称使用可以防止在进行修改后出现问题,却又无法回到原始位置。

问:line30的功能是什么?

答:line30代码为  mov es:[di], cx

       其功能是为了将数值和颜色送入显存中,而根据代码es的值为B800H,di初始值为0。

       因此,这句代码的功能是将带有颜色属性的字数据字符写入到地址为B800:0的显存中。

 

3.实验任务3

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

        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

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

使用u命令反汇编:

 

 

使用g命令执行到line15:

 

 

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

 

 

 

 

子任务2
  对Task_3.asm源代码进行修改、完善,把Task_3.asm中用于输出以0结尾的字符串的子程序加进来,实现对转换后的字符串进行输出。

加入代码:

 

 

 

 运行Task_3.exe,得到结果图如下:

 

 

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

 

4.实验任务4

 

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

对Task_4.asm进行汇编、连接、运行:

 

 

 

 

 

问:line12-19实现的功能是?

答:一直从键盘读入字符,并将读入的字符存放到data数据段当中,直到遇到输入符号为'#'为止。

问:line21-27实现的功能是?

答:将存放在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); }

我的vs没有安装c程序的使用,因此我用Dev/c++代替:

高级语言中参数传递是通过栈来实现的。

被调函数的返回值在该例中是通过eax寄存器来存储的,程序返回到主调函数可以通过eax寄存器来获取被调函数的返回值。

函数调用过程中参数的如入栈顺序:参数b先入栈,参数a后入栈。

 

posted on 2020-12-16 20:12  cox4869  阅读(193)  评论(3)    收藏  举报