|
主题 : : 实验10第一题,各位挑下刺,看有没有改进空间 [待解决] |
回复[ 4次 ]
点击[ 403次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2011-10-08 17:30 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:2
注册日期:2010-11-24 11:04 |
程序:
assume cs:codesg
datasg segment
db 'Welcome to masm!',0
datasg ends
codesg segment
start:
mov dh,8
mov dl,3
mov cl,2
mov ax,datasg
mov ds,ax
mov si,0
call show_str
mov ax,4C00H
int 21H
show_str:
push es
push ax
push bx
push cx
push dx
push si
mov ax,0B800H
mov es,ax
mov al,0A0H ; 计算行偏移
mul dh
mov bx,ax
add dl,dl ; 计算列偏移
add bx,ax ; 累加行列偏移,确定显示地址
mov ah,cl
mov ch,0
show: mov cl,[si]
jcxz return
mov al,cl
mov es:[bx],ax
inc si
add bx,2
jmp short show
return: pop si
pop dx
pop cx
pop bx
pop ax
pop es
ret
codesg ends
end start
说明一点:
题目要求行的取值范围是(0~24)而显示缓冲区最大25行,也就说起始下标是0开始的,直接乘以0A0H则可算出行的偏移地址。 传入参数的8按照0为起始地址来看,正确的显示应该是第九行。 同理,3列应该显示在第四列。 | | |
|
|
|
|
[第1楼]
[ 回复时间:2011-10-08 23:01 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:2
注册日期:2010-11-24 11:04 |
继续发第二题:
assume cs:codeseg
codeseg segment
start:
mov ax,4240H
mov dx,000FH
mov cx,0AH
call divdw
mov ax,4C00H
int 21H
divdw:
push bx ;使用到的bx寄存器入栈
push ax ;将低十六位暂时入栈
mov ax,dx ;运算高十六位,因为除数cx是十六位,所以被除数为32位,低位存放到ax中
mov dx,0 ;将除法运算高位置零
div cx ; H/N 高十六位除法运算,商存储在ax中,余数在dx中
mov bx,ax ; 将商临时存放到bx中
pop ax ; 将被除数低16位出栈,这一步完成rem(H/N)*65536+L,余数乘以65536就是将低16位ax置为高16位dx,pop ax将低位放入ax,等同加上L
div cx
mov cx,dx ; 将最后余数放入cx(题目要求)
mov dx,bx ; 将临时变量bx中的值(高位)放入dx
pop bx
ret
codeseg ends
end start
结果:(dx)=0001H,(ax)=86A0H,(cx)=0 | | |
|
|
|
|
[第2楼]
[ 回复时间:2011-10-08 23:01 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:2
注册日期:2010-11-24 11:04 |
继续发第二题:
assume cs:codeseg
codeseg segment
start:
mov ax,4240H
mov dx,000FH
mov cx,0AH
call divdw
mov ax,4C00H
int 21H
divdw:
push bx ;使用到的bx寄存器入栈
push ax ;将低十六位暂时入栈
mov ax,dx ;运算高十六位,因为除数cx是十六位,所以被除数为32位,低位存放到ax中
mov dx,0 ;将除法运算高位置零
div cx ; H/N 高十六位除法运算,商存储在ax中,余数在dx中
mov bx,ax ; 将商临时存放到bx中
pop ax ; 将被除数低16位出栈,这一步完成rem(H/N)*65536+L,余数乘以65536就是将低16位ax置为高16位dx,pop ax将低位放入ax,等同加上L
div cx
mov cx,dx ; 将最后余数放入cx(题目要求)
mov dx,bx ; 将临时变量bx中的值(高位)放入dx
pop bx
ret
codeseg ends
end start
结果:(dx)=0001H,(ax)=86A0H,(cx)=0 | | |
|
|
|
|
[第3楼]
[ 回复时间:2011-10-09 15:33 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:2
注册日期:2010-11-24 11:04 |
第一题有一行错了
add bx,ax ; 累加行列偏移,确定显示地址
应该修改为:
and dh,0H
add bx,dx | | |
|
|
|
|
[第4楼]
[ 回复时间:2011-10-11 18:55 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:2
注册日期:2010-11-24 11:04 |
第三题想了N久,其它都简单,主要是转换为十进制后的倒序问题,用栈来倒序是简单,但容易出问题,不说栈操作的是两个字节,而且还让子程序依赖栈,总之这种方法不理想。
那剩余的方法就是用寄存器了,在si存入0的时候其实就得出了数字的空间长度,知道长度,起始位置,那倒序操作最多循环N/2+1次,下面是我的代码(通过测试):
; 实验十(3)
; 名称:dtoc
; 功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
; 参数:(ax)=word型数据
; ds:si指向字符串的首地址
; 范围:无
; 应用举例:编程,将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。
assume cs:codesg
datasg segment
db 10 dup (0)
datasg ends
codesg segment
start:
mov ax,12666
mov bx,datasg
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4C00H
int 21H
; 转换进制
dtoc:
push ax
push dx
push bx
push cx
push si
push di
mov di,si
mov bx,10
tran: and dx,0H
div bx
mov cx,ax
add dl,30H
mov [si],dl
inc si
jcxz sort
jmp short tran
sort: mov byte ptr [si],0
mov ax,si
mov bl,2
div bl
dec si
mov cl,ah
jcxz pp
inc al
pp: mov cl,al
swap: mov al,[di]
mov ah,[si]
mov [si],al
mov [di],ah
inc di
dec si
loop swap
pop di
pop si
pop cx
pop bx
pop dx
pop ax
ret
; 显示字符串
show_str:
push es
push ax
push bx
push cx
push dx
push si
mov ax,0B800H
mov es,ax
mov al,0A0H ; 计算行偏移
mul dh
mov bx,ax
add dl,dl ; 计算列偏移
and dh,0H
add bx,dx ; 累加行列偏移,确定显示地址
mov ah,cl
mov ch,0
show: mov cl,[si]
jcxz return
mov al,cl
mov es:[bx],ax
inc si
add bx,2
jmp short show
return: pop si
pop dx
pop cx
pop bx
pop ax
pop es
ret
codesg ends
end start | | |
|