1.实验任务1
汇编程序源码:
assume cs:code, ds:data data segment x db 1, 9, 3 len1 equ $ - x ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是3 y dw 1, 9, 3 len2 equ $ - y ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是9 data ends code segment start:mov ax, data mov ds, ax mov si, offset x ; 取符号x对应的偏移地址0 -> si mov cx, len1 ; 从符号x开始的连续字节数据项个数 -> cx 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 ; 取符号y对应的偏移地址3 -> si mov cx, len2/2 ; 从符号y开始的连续字数据项个数 -> cx 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
①由机器码得,跳转位移量的补码为F2,换算成十进制为-14,所以跳转位移量是-14。机器码E2是loop跳转命令,其下一条命令的偏移地址是1Bh,减14后就是后标号s1其后指令的偏移地址。
②由机器码得,跳转位移量的补码为F0,换算成十进制为-16,所以跳转位移量是-16。机器码E2是loop跳转命令,其下一条命令的偏移地址是39h,减14后就是后标号s2其后指令的偏移地址。
③反汇编截图:
2.实验任务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
①(ax)=0021 h,(bx)=0026 h,(cx)=076C h
②调试后结果:
与分析结果一致。
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, len s1:call printNumber call printSpace inc si loop s1 mov ah, 4ch int 21h printNumber: mov ah, 0 mov al, [si] mov bl, 10 div bl mov bx, ax mov ah, 2 mov dl, bl or dl, 30h int 21h mov ah, 2 mov dl, bh or dl, 30h 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 bl, 2 mov bh, 0 call printStr mov bl, 4 mov bh, 24 call printStr mov ah, 4ch int 21h printStr: mov ax, 0b800h mov es, ax mov si, offset str mov cx, len mov ax, 00a0h mul bh mov di, ax s: mov al, [si] mov es:[di], al mov es:[di+1], bl inc si add di, 2 loop s ret code ends end start
测试结果如下:
与预期测试结果相同。
5.实验任务5
实验源码:
assume cs:code, ds:data data segment stu_no db '201983290275' len = $ - stu_no data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h mov es, ax mov al, 24 mov dl, 80 mul dl mov cx, ax mov di, 0 s1:mov al, 17h ;除最后一行页面设置蓝色 mov es:[di], byte ptr 20h mov es:[di+1], al add di, 2 loop s1 mov ax, 00a0h mov bh, 24 mul bh mov di, ax call printStr mov si, offset stu_no mov cx, len call printNum call printStr mov ah, 4ch int 21h printStr: mov ax, 80 sub ax, len mov bl, 2 div bl mov ch, 0 mov cl, al s2:mov ah, 17h mov al, '-' mov es:[di], ax add di, 2 loop s2 ret printNum: s3:mov ah, 17h mov al, [si] mov es:[di], ax inc si add di, 2 loop s3 ret code ends end start
测试结果如下:
与预期测试结果相同。
6.实验结论
通过本次实验,我初步学会了使用call跳转语句来调用一个子程序,在子程序中必须有一个ret来跳转回原来的程序。call执行时将现在的ip或cs与ip存入栈中。ret跳转到的就是从栈中取出的地址和偏移地址,出栈时先出的是偏移地址。
关于len equ $ - x 中len为到x的长度,$指下一个数据项的偏移地址。