实验9
1. 实践10.1节内容(p191~192页)
补全检测点10.1中程序
assume cs:code, ss:stack
stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16 ;指向栈顶
mov ax,1000h
push ax ;cs的值入栈
mov ax,0
push ax ;ip的值入栈
retf ;修改cs和ip的值,先pop ip,后cs
code ends
end start
用Debug查看检测点10.1程序

执行retf后

2. 实践10.3节内容(p192~193页)
用Debug查看检测点10.2程序

Ax的值为0006h
3. 实践10.4节内容(p193页)
用Debug查看检测点10.3程序


程序执行完后ax的值为1010h
4. 实践10.5节内容(p194页)
用Debug查看检测点10.4程序


程序执行完后ax的值为000Bh
5. 实践10.6节内容(p194~p196页)
检测点10.5中程序
assume cs:code
data segment
dw 8 dup (0)
data ends
code segment
start:
mov ax,data
mov ss,ax
mov sp,16 ;指向栈顶
mov word ptr ss:[0], offset s ;将标号s处的偏移地址赋值到ss:[0]中,即栈的第8个字
mov ss:[2],cs ;将寄存器CS(标号s处的段地址)赋值到ss:[2]中,即栈的第7个字
call dword ptr ss:[0] ;跳转到标号s处执行
nop
s:
mov ax,offset s ;将标号s处的偏移地址赋值到AX
sub ax,ss:[0cH] ;(ss:[0cH])为栈顶元素,即nop指令的偏移地址,即s.IP-nop.IP为nop指令长度,即为1
mov bx,cs
sub bx,ss:[0eH] ;(ss:[0eH])为第二栈顶元素,即nop指令的段地址,即cs-nop.CS,即为0
mov ax,4c00h
int 21h
code ends
end start
用Debug查看检查点10.5程序

ax的值为1,bx的值为0
6. 实验10 编写子程序1—显示字符串(p206页)
描述:
名称:show_str
功能:在指定的位置用指定的颜色,显示一个用0结束的字符串。
参数:(dh)=行号(取值范围0-24), (dl)=列号(取值范围0-79)
(cl)=颜色,ds:si指向字符串的首地址
返回:无
assume cs:code, ss:stack
data segment
db 'Welcome to masm!',0 ;ds:si
data ends
stack segment
db 128 dup (0)
stack ends
code segment
start:mov ax,stack
mov ss,ax
mov sp,128 ;指向栈顶
mov dh,8 ;在第8行写入
mov dl,3 ;在第3列写入
mov cl,2 ;字符颜色属性
mov ax,data
mov ds,ax
mov si,0
call show_str
mov ax,4c00h
int 21h
show_str:
;数据到的地方(显示)es:di
mov ax,0B800h
mov es,ax ;段地址es
mov al,160
mul dh
mov bx,ax
mov al,2
mul dl
add bx,ax ;偏移地址di
mov al,cl ;保存颜色属性
s:
mov cx,0
mov cl,ds:[si] ;cx读取字符
jcxz showStringRet ;读到0时退出
mov es:[bx+di+0],cl ;偶数地址写入字符
mov byte ptr es:[bx+di+1],al;奇数地址写入字符属性
add di,2 ;移动到下一个要写入的地址
inc si ;移动到下一个要读取的数据
jmp s ;循环读取字符
showStringRet:
ret ;子程序返回
code ends
end start

7.实验10 编写子程序2—解决除法溢出的问题(p207~208页)
描述:
名称:divdw
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
参数:(ax)=dword型数据的低16位,
(dx)= dword型数据的高16位,
(cx)=除数
返回:(dx)= 结果的高16位,
(ax)=结果的低16位,
(cx)=余数
assume cs:code
code segment
start:
mov ax,4240h ;被除数低16位
mov dx,00Fh ;被除数高16位
mov cx,0Ah ;除数
call divdw ;执行运算
mov ax,4c00h
int 21h
divdw:
mov bx,ax ;将ax中值暂存到BX中
mov ax,dx ;针对X高16位的除法,将被除数X高16位存放在AX中
mov dx,0 ;除法H/N中高16位设为0
div cx ;执行除法H/N,此时结果的商(H/N的高16位)存放在AX中、余数存放在DX中
mov si,ax ;si暂存H/N结果的商
mov ax,bx ;将被除数低16位的内容放到AX中
div cx ;执行加法右边除法[rem(H/N)*65536+L]/N,结果商在AX、余数在DX
mov cx,dx ;余数
mov dx,si ;高16位
ret
code ends
end start

8.实验10 编写子程序3—数值显示(p209~210页)
描述:
名称:dtoc
功能:将word型数据转变为表示十进制的字符串,字符串以0结尾。
参数:(ax)=word型数据
ds:si指向字符串的首地址
返回:无
assume cs:code,ds:data,ss:stack
data segment
dw 123,12666,1,8,3,38 ;ds:si
data ends
string segment
db 50 dup (0) ;es:di存放转换后的字符串
string ends
stack segment
db 128 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
mov bx,data
mov ds,bx
mov si,0
call dtoc ;转换为十进制数的字符串
mov ax,string ;要将字符串显示的数据来源
mov ds,ax
mov si,0
mov ax,0
mov cx,6 ;六个数据输出六次
mov dh,8 ;写入的行号
show: push cx
mov dl,3 ;写入的列号
mov cl,2
call show_str ;将字符串显示在屏幕
pop cx
inc dh
loop show
mov ax,4c00h
int 21h
dtoc:
mov bx,string
mov es,bx
mov di,0
mov cx,6 ;六个数外循环6次
loop_zone:
push cx ;保存外循环次数
mov dx,0 ;记录数据的位数
mov ax,ds:[si] ;被除数写入ax寄存器
short_div: ;一个数字
push dx ;保存dx(数据位数)
mov bx,10 ;bx存放除数
mov dx,0 ;置零,放被除数高位
div bx ;32/16,被除数在ax中,结果商在ax下,余数在dx
add dl,30h ;余数转为ASCII码
mov cx,dx ;用cx保存余数
pop dx ;dx出栈
push cx ;余数入栈
inc dx ;数字位数计数+1
mov cx,ax ;判断商是否为0
jcxz shortDivRet ;商为0结束
jmp short short_div ;商不为0继续除
shortDivRet:
pop ax ;将在栈顶的余数出栈
mov byte ptr es:[di],al ;保存到string段
inc di
dec dx
mov cx,dx ;将剩余位数传给cx
jcxz last ;完成一个完整数据传到string段跳转
jmp short shortDivRet ;没有继续传
last: ;在string段中每个数据后加0
mov ah,0
mov byte ptr es:[di],ah
inc di
pop cx
add si,2
loop loop_zone
ret
show_str:
;数据到的地方(显示)es:di
mov ax,0B800h
mov es,ax ;段地址es
mov di,0 ;将所给的行列转换到偏移地址di中存放
mov al,160
mul dh
mov di,ax
mov al,2
mul dl
add di,ax ;偏移地址di
mov dl,cl ;dl保存颜色属性
s:
mov cx,0
mov cl,ds:[si] ;cx读取字符
jcxz showStringRet ;读到0时退出
mov ch,dl ;高位字符属性
mov es:[di],cx ;偶数地址写入字符
add di,2 ;移动到下一个要写入的地址
inc si ;移动到下一个要读取的数据
jmp short s ;循环读取字符
showStringRet:
inc si ;si指向0的下一个字符
ret ;子程序返回
code ends
end start
