汇编语言实验三
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
结果如下: