实验三 转移指令跳转原理及其简单应用编程
实验任务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:
loop指令对应的机器码是(E2F2)16,其中(F2)16是补码表示的偏移量,换算成十进制数是-14。当前loop指令的长度是2字节,下一条指令的偏移地址是(001B)16,减去(14)10刚好是标号s1对应的偏移地址(000D)16.
② 回答问题2:
与问题1相似,机器码中偏移量的补码是(F0)16,对应十进制-16。下一条指令的偏移地址是(0039)16,减(16)10得标号s2的偏移地址(0029)16.
实验任务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中是标号s1的偏移地址,bx中是标号s2的偏移地址,cx中是标号s2的段地址。
注意到两条call指令一个是短转移一个是远转移。执行第一个call时,将当前命令的下一条命令的偏移地址(IP)压入栈,也就是将标号s1的偏移地址压入栈;随后(IP)变为内存单元偏移地址为0的字单元中的数值,由于程序已经将该字单元赋值为标号s1的偏移地址,所以程序看起来就是顺序执行了下面的命令而没有进行跳转,将刚刚压入栈的偏移地址弹出给寄存器ax;执行第二条远转移call时,依次将下一条指令的段地址(CS)和偏移地址(IP)压入栈,后面的过程与之前类似。
实验截图:
实验任务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, 0
mov cx, len
s:
mov ah, 0
mov al, [si]
inc si
call printNumber
call printSpace
loop s
mov ah, 4ch
int 21h
printNumber:
mov bl, 10
div bl
mov bx, ax
mov ah, 2
add bl, 48
mov dl, bl ;商
int 21h
add bh, 48
mov dl, bh ;余数
int 21h
ret
printSpace:
mov ah, 2
mov dl, 32 ;空格的ASCII码
int 21h
ret
code ends
end start
测试截图:
实验任务4
源程序代码:
assume cs:code, ds:data
data segment
str db 'try'
len equ $ - str
data ends
stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
mov si, 0 ;数据段偏移地址
mov cx, len ;字符串长度
mov bh, 0 ;行号
mov bl, 02h ;黑底绿字
call printStr
mov si, 0
mov cx, len
mov bh, 24
mov bl, 04h ;黑底红字
call printStr
mov ah, 4ch
int 21h
printStr:
mov ax, 0b800h
mov es, ax
push bx ;暂存颜色
mov bl, bh
mov bh, 0 ;bx中现在是行号(0-24)
mov ax, 00a0h ;一行的字节数
mul bx
mov bx, ax ;bx得到行首偏移地址
pop ax
mov ah, al
s:
mov al, [si]
mov es:[bx+si], ax
inc bx
inc si
loop s
ret
code ends
end start
测试截图:
实验任务5
程序源代码:
assume cs:code, ds:data
data segment
stu_no db '201983290485'
len = $ - stu_no
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, 0b800h
mov es, ax
mov si, 1
mov cx, 7d0h ;2000次循环
s:
mov byte ptr es:[si],17h ;00010111
add si, 2
loop s
mov si, 0f00h
mov cx, 80
s1:
mov byte ptr es:[si], 2dh ;-----
add si, 2
loop s1
mov si, 0f44h ;最后一行中间
mov cx, 12
mov bx, 0
s2:
mov al, [bx]
mov es:[si], al
add si, 2
inc bx
loop s2
mov ax, 4c00h
int 21h
code ends
end start
测试截图: