实验3 转移指令跳转原理及其简单应用编程
实验任务1
- 给出程序task1.asm源码及运行截图
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
-
问题①
loop跳转的位移量为-14;loop循环指令进行的是短转移,8位位移 = 标号处的地址 - loop指令后的第一个字节的地址; -
问题②
loop跳转的位移量为-16;loop循环指令进行的是短转移,8位位移 = 标号处的地址 - loop指令后的第一个字节的地址; -
问题③
在debug中进行调试观察的反汇编截图
实验任务2
- 程序task2.asm源码
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
- 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) =? 寄存器(bx) = ? 寄存器(cx) = ?
ax中值为标号s1处的偏移地址,bx中值为标号s2的偏移地址,cx中值为cs存储的地址。 - 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果与理论分析结果是否一致。
实验任务3
- 源程序task3.asm
assume ds:data, cs:code
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,0
mov cx,len
s: call printNumber;
call printSpace;
inc si
loop s
mov ax,4c00h
int 21h
printNumber:
mov ah,0
mov al, [si]
mov bl, 10
div bl ;ax中的数据除以十进制10
mov bl,al ;al存储除法操作的商
mov bh,ah ;ah存储除法操作的余数
mov ah,2
mov dl,bl
add dl,30h ;将dl中的二进制数转换为十进制数输出。
int 21h
mov ah,2
mov dl,bh
add dl,30h
int 21h
ret
printSpace:
mov ah,2
mov dl,' '
int 21h
ret
code ends
end start
- 测试截图
实验任务4
- 源程序task4.asm
assume ds:data, cs:code
data segment
str db 'try'
len equ $ - str
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov cx,len;
mov bh,0 ;首行
mov bl,00000010B;绿色 ;bl保存颜色
call printStr
mov si,0
mov cx,len;
mov bh,24 ;
mov bl,00000100B;红色
call printStr
mov ax,4c00h
int 21h
printStr:
mov ax,0b800h
mov es,ax ;存储显存段地址
mov al,bh
mov dl,160
mul dl ;行号*160得到显存中的位置,保存在ax中
mov di,ax
s: mov al,ds:[si] ;al存储字符串中的字符
mov es:[di],al ;es:[di]是显存地址,首先存储字符
inc si
inc di
mov es:[di],bl ;然后存储颜色格式
inc di
loop s
ret
code ends
end start
- 测试截图
实验任务5
- 源程序task5.asm
assume cs:code, ds:data
data segment
stu_no db '201983290125'
len = $ - stu_no
len1 = (80-len)/2
data ends
code segment
start:
mov ax,data
mov ds,ax
mov bl,00010000b
call color ;输出背景颜色
mov si,0
mov bl,00010111b ;字符颜色
mov bh,24 ;行号
call studentnumber ;输出学号
mov ah,4ch
int 21h
color:
mov ax,0b800h
mov es,ax ;保存显示缓冲区段地址
mov al,25
mov dx,80
mul dx
mov cx,ax ;显示缓存区一页的大小为4000字节
mov al,' ' ;
mov di,0
s: mov es:[di],al ;存储数据
inc di
mov es:[di],bl ;存储格式
inc di
loop s
ret
studentnumber:
mov ax,0b800h
mov es,ax
mov al,bh
mov dl,160
mul dl
mov di,ax
mov al,'-' ;输出学号前面的"-"
mov cx,len1
s1: mov es:[di],al
inc di
mov es:[di],bl
inc di
loop s1
mov cx,len ;输出学号
s2: mov al,ds:[si]
mov es:[di],al
inc si
inc di
mov es:[di],bl
inc di
loop s2
mov al,'-' ;输出学号后面的"-"
mov cx,len1
s3: mov es:[di],al
inc di
mov es:[di],bl
inc di
loop s3
ret
code ends
end start
*测试截图