汇编语言实验三

1.任务一

程序代码如下:

assume cs:code, ds:data

data segment
    x db 1, 9, 3
    len1 equ $ - x

    y dw 1, 9, 3
    len2 equ $ - y
data ends

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

    mov si, offset x
    mov cx, len1
    mov ah, 2
 s1:mov dl, [si]
    or dl, 30h
    int 21h

    mov dl, ' '
    int 21h

    inc si
    loop s1

    mov ah, 2
    mov dl, 0ah
    int 21h

    mov si, offset y
    mov cx, len2/2
    mov ah, 2
 s2:mov dx, [si]
    or dl, 30h
    int 21h

    mov dl, ' '
    int 21h

    add si, 2
    loop s2

    mov ah, 4ch
    int 21h
code ends
end start

程序执行结果如下:

 

1.

 EQU 伪指令把一个符号名称与一个整数表达式或一个任意文本连接起来;

“$” 是汇编语言中的一个预定义符号,等价于当前正汇编到的段的当前偏移值;

offset:取标号的偏移地址;

2.回答问题

(1)

 

 loop处机器码为E2F2,指令实现的是段内短转移,范围是-128~127,后两位是位移量的补码形式,转换为二进制是11110010,

转换为原码为10001110,转化为十进制为-(2+4+8)=-14,即向前14个字节,loop处偏移量为0019H,转换为十进制是16+9=25,

又因为loop指令占2字节,所以读取完这条指令ip值自动+2,即为25+2=27;27-14=13为跳转到的指令的偏移地址,转换为16进制为

000D,发现正是s1标号处的偏移地址,跳转成功。

(2)

 

 同上,loop指令机器码为E2F0,位移量补码11110000,原码10010000,十进制-16,当前指令读取完毕ip值变为0039,即9+16*3=57,57-16

=41=2*16+9,转化为16进制为0029,即为标号s2处偏移地址。

 

2.实验任务二

assume cs:code, ds:data

data segment
    dw 200h, 0h, 230h, 0h
data ends

stack segment
    db 16 dup(0)
stack ends

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

    mov word ptr ds:[0], offset s1
    mov word ptr ds:[2], offset s2
    mov ds:[4], cs

    mov ax, stack
    mov ss, ax
    mov sp, 16

    call word ptr ds:[0]
s1: pop ax

    call dword ptr ds:[2]
s2: pop bx
    pop cx

    mov ah, 4ch
    int 21h
code ends
end start

 

(1)查阅资料可知:

call word ptr 内存单元地址,相当于push IP AND jmp word ptr 内存单元地址
call dword ptr 内存单元地址,相当于push CS AND push IP AND jmp dword ptr 内存单元地址。

(ax)=offset s1;

call dword ptr ds:[2]执行后,栈依次弹出这条call指令的下一条指令的ip和cs;下一条指令的cs就为code段起始地址,ip为编号s2;

(bx)=offset s2;

(cx)=code

(2)结果如下:

 

 可见执行完call指令后,ip下一条指令的偏移地址0021,即将0021压栈,pop ax后,ax为0021;

 

 应当进栈的cs:ip为076c:0026,发现bx=0026,ip先出栈,cx=076c,cs再出栈。

 

3.实验任务3

assume cs:code, ds:data

data segment
        x db 99, 72, 85, 63, 89, 97, 55
        len equ $ - x
data ends

code segment
start:
        mov ax, data
        mov ds, ax
        mov si, offset x ;第一个数据的偏移地址
        mov cx, 7
        mov byte ptr ds:[8],10 

s:      mov ah, 0
        mov al, [si] ;被除数
        div byte ptr ds:[8] 
        call printNumber
        call printSpace

        inc si ;db一个数据一字节,加一
        loop s

        mov ax, 4c00h
        int 21h

printNumber:
        mov bx, ax 
        or bh, 30h ;转为acsii码
        or bl,30h
        mov ah,2 
        mov dl,bl ;低位商
        int 21h;
        mov dl,bh ;高位余数
        int 21h;
        ret

printSpace:
        mov ah, 2
        mov dl, ' '
        int 21h
        ret

code ends
end start

结果如下:

 

 

4.实验任务4

 

assume cs:code, ds:data

data segment
        str db 'try'
        len equ $ - str
data ends

code segment
start:
        mov ax, data
        mov ds, ax
        mov ax, 0b800h 
        mov es, ax ;进入显存

        mov si, offset str;第一个字符偏移地址
        mov cx, len
        mov bl, 2h ;颜色为绿色
        mov bh, 0 ;行数为第0行
        call printStr

        mov si, offset str
        mov cx, len
        mov bl, 4h ;颜色为红色
        mov bh, 24 ;行数为第24行
        call printStr

        mov ax, 4c00h
        int 21h

printStr:
        mov al, 160 ;一行80字符
        mul bh
        mov di, ax ;ax为第bh行的偏移量,行*列,从es:di开始输出字符
s:      mov ah, ds:[si]
        mov es:[di], ah ;字符
        mov es:[di+1], bl ;颜色

        add di, 2
        inc si
        loop s
        ret

code ends
end start

结果如下:

 

 

5.实验任务5

代码如下:

assume ds:data, cs:code

data segment
    stu_no db '201983290125'
    len = $ - stu_no
data ends

code segment
start:
        mov ax, data
        mov ds, ax
        mov ax, 0b800h
        mov es, ax
        mov cx, 4000 ;每一屏字节数:80×25×2 = 4000字节
        mov di, 0
        mov ah,17h ;蓝底白字

s1:    mov al, 0
        mov es:[di], al;低字节字符
        mov es:[di+1], ah;高字节颜色、闪烁
        add di, 2
        loop s1
        ;整个屏幕编程蓝底
        ;最后一行开始的-
        mov di, 3840 ;第24行开始
        mov cx, 34 ;一行160字节,显示字符串12*12=24字节,两边136/4=34,即2边各打印34个-
        mov ah, 17h
s2:    call printSign
        add di, 2
        loop s2

        ;打印学号
        mov di, 3908 ;学号开始偏移地址
        mov si, offset stu_no
        mov cx, len;循环次数即学号位数
        mov ah, 17h;蓝底白字
s3:    call printStu
        inc si
        add di, 2
        loop s3

        ;最后一行最后的-
        mov di, 3932 ;=3840-68
        mov cx, 34
        mov ah, 17h
s4:    call printSign
        add di, 2
        loop s4

        mov ax, 4c00h
        int 21h

printStu:
        mov al, [si];学号数字
        mov es:[di], al
        mov es:[di+1], ah
        ret

printSign:
        mov al, 2Dh ;-
        mov es:[di], al
        mov es:[di + 1], ah
        ret

code ends
end start

 

结果如下:

 

posted @ 2021-11-27 17:42  玉骢  阅读(82)  评论(3编辑  收藏  举报