输入无符号的十进制数,存入BX
指令重点:
mul判断溢出
如果8位*
8位=8位,无溢出,CF=OF=0;
如果8位*
8位=16位,结果的高8位全为0,无溢出,CF=OF=0,
否则CF=OF=1。
算法核心:
bx*10+输入的字符
当bx*10
大于65535,溢出;
当bx*10+输入的字符
大于65535,溢出。
data segment
string db 0dh,0ah,"overflow!",'$'
data ends
stack segment stack
dw 100 dup (?)
top label word
stack ends
code segment
assume cs:code,ds:data,ss:stack
main proc far
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
lea sp,top
mov bx,0 ;bx清零
mov si,10 ;si为乘数/除数
mov cx,0 ;统计输入合法字符的个数
L1:
mov ah,7 ;7号功能输入,不回显
int 21h
cmp al,0dh ;输入回车,以10进制显示输出bx
je print
cmp al,30h ;输入字符小于30h,重新输入
jb L1
cmp al,39h ;输入字符大于39h,重新输入
ja L1
mov dl,al ;合法字符,回显
mov ah,2
int 21h
inc cx ;合法字符+1
and dx,0fh ;屏蔽高12位,只留下低4位0-9
mov ax,dx
xchg ax,bx ;交换ax,bx(因为mul默认在ax)
mul si ;结果在(dx,ax)
;判断溢出
;乘法指令的CF和OF
;如果8位*8位=8位,无溢出
;如果8位*8位=16位,结果的高8位全为0,则CF=OF=0,否则CF=OF=1
jc overflow
add bx,ax ;如果ax*10刚好等于65535,加上bx可能会溢出
jc overflow
jmp L1
;以10进制显示输出bx
print:
cmp cx,0 ;输入的合法字符为0,即一开始就敲了回车,直接退出
je exit
;回车和换行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
mov cx,0 ;统计余数个数
mov ax,bx ;被除数(bx,ax)
mov dx,0
L2:
div si
push dx ;余数进栈
inc cx ;余数个数+1
cmp ax,0 ;商为0,跳转到L3
je L3
mov dx,0 ;dx清零作为新的被除数
jmp L2
L3:
pop dx
add dl,30h ;转换成数字字符
mov ah,2
int 21h
loop L3
cmp cx,0 ;跳过下面的overflow
jmp exit
;溢出在屏幕上显示"overflow!"
overflow:
lea dx,string
mov ah,9
int 21h
exit:
mov ah,4ch
int 21h
main endp
code ends
end main
输入带符号的十进制数,存入BX
输入的第一位可能是’+‘、’-'、数字,其他位都是数字。
实现的核心思想是:
输入的符号和数字分开,用一个寄存器记录输入的符号,bp=0
为正数,bp=1
为负数;
其他数字以无符号数的形式输入,范围为0-65535,判断溢出的方法跟上一题一样;
输完数字敲回车的时候,再去判断有符号数的溢出:
如果bp=1
,即bx是负数,对bx求补,根据符号位判断溢出,bx求补的符号位为1,则无溢出;bx求补的符号位为0,则溢出;
如果bp=0
,即bx是正数,根据符号位判断溢出,bx的符号位为0,则无溢出;bx的符号位为1,则溢出。
补充
求负数的二进制:对应正数的补码
最高位为1:负数
最高位为0:正数
data segment
string db 0dh,0ah,"overflow!",'$'
data ends
stack segment stack
dw 100 dup (?)
top label word
stack ends
code segment
assume cs:code,ds:data,ss:stack
main proc far
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
lea sp,top
mov bx,0
mov cx,0 ;统计合法的数字字符个数
mov si,10
mov bp,0 ;符号位默认为0(正数)
mov ah,7 ;输入第一个字符
int 21h
cmp al,0dh ;输入回车,退出
je exit
cmp al,'-' ;判断输入的第一个字符
jne L1 ;不是负号,跳转到L1继续判断
mov bp,1 ;输入负号,更改符号位
mov dl,al ;显示负号
mov ah,2
int 21h
jmp L2 ;跳转到L2继续输入数字字符
L1:
cmp al,'+'
jne L3 ;不是正号,跳转到L3继续判断
mov bp,0 ;输入正号,更改符号位
mov dl,al ;显示正号
mov ah,2
int 21h
jmp L2 ;跳转到L2继续输入数字字符
L2:
mov ah,7
int 21h
cmp al,0dh ;输入回车,跳转到以10进制显示bx
je print
L3:
cmp al,30h ;小于30h,继续输入
jb L2
cmp al,39h ;大于39h,继续输入
ja L2
mov dl,al ;显示合法的数字字符
mov ah,2
int 21h
inc cx ;合法的数字字符+1
and dx,0fh ;屏蔽dx高12位
mov ax,dx
xchg ax,bx ;交换ax和bx
mul si ;ax*10
;数字部分以无符号数输入
;限制数字部分的输入范围0-65535
jc overflow
add bx,ax
jc overflow
jmp L2 ;无溢出,跳转到L2继续输入数字字符
print:
cmp cx,0 ;判断合法的数字字符个数,cx为0退出
je exit
;接下来判断有符号数的溢出
cmp bp,1
je negative ;判断负数的溢出
cmp bp,0
je positive ;判断正数的溢出
negative:
neg bx ;bx是负数,求补
add bx,0 ;这条指令会改变psw,接下来判断符号位
jns overflow ;符号位是0,溢出
neg bx ;为了下面显示bx,要把bx还原
;回车换行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
mov dl,'-' ;无溢出,显示字符数前加一个'-'
mov ah,2
int 21h
jmp L4 ;跳转到L4以10进制显示bx
positive:
add bx,0 ;bx是正数
js overflow ;符号位是1,溢出
;回车换行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
mov dl,'+' ;无溢出,显示字符数前加一个'+'
mov ah,2
int 21h
jmp L4 ;跳转到L4以10进制显示bx
L4:
mov cx,0 ;余数个数
mov ax,bx ;被除数(dx,ax)
mov dx,0
L5:
div si
push dx ;余数进栈
inc cx ;余数个数+1
cmp ax,0 ;商为0,退出
je L6
mov dx,0 ;把dx清零作为新的被除数(dx,ax)
jmp L5
L6:
pop dx
add dl,30h ;转换成数字字符
mov ah,2
int 21h
loop L6
cmp cx,0 ;为了跳过下面的overflow
jmp exit
overflow:
lea dx,string
mov ah,9
int 21h
exit:
mov ah,4ch
int 21h
main endp
code ends
end main
输入一个有符号的十进制数,以十六进制输出
data segment
string db 0dh,0ah,"overflow!",'$'
data ends
stack segment stack
dw 100 dup (?)
top label word
stack ends
code segment
assume cs:code,ds:data,ss:stack
main proc far
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
lea sp,top
mov bx,0
mov cx,0 ;统计合法的数字字符个数
mov si,10
mov bp,0 ;符号位默认为0(正数)
mov ah,7 ;输入第一个字符
int 21h
cmp al,0dh ;输入回车,退出
je exit
cmp al,'-' ;判断输入的第一个字符
jne L1 ;不是负号,跳转到L1继续判断
mov bp,1 ;输入负号,更改符号位
mov dl,al ;显示负号
mov ah,2
int 21h
jmp L2 ;跳转到L2继续输入数字字符
L1:
cmp al,'+'
jne L3 ;不是正号,跳转到L3继续判断
mov bp,0 ;输入正号,更改符号位
mov dl,al ;显示正号
mov ah,2
int 21h
jmp L2 ;跳转到L2继续输入数字字符
L2:
mov ah,7
int 21h
cmp al,0dh ;输入回车,跳转到以16进制显示bx
je print
L3:
cmp al,30h ;小于30h,继续输入
jb L2
cmp al,39h ;大于39h,继续输入
ja L2
mov dl,al ;显示合法的数字字符
mov ah,2
int 21h
inc cx ;合法的数字字符+1
and dx,0fh ;屏蔽dx高12位
mov ax,dx
xchg ax,bx ;交换ax和bx
mul si ;ax*10
;数字部分以无符号数输入
;限制数字部分的输入范围0-65535
jc overflow
add bx,ax
jc overflow
jmp L2 ;无溢出,跳转到L2继续输入数字字符
print:
cmp cx,0 ;判断合法的数字字符个数,cx为0退出
je exit
;接下来判断有符号数的溢出
cmp bp,1
je negative ;判断负数的溢出
cmp bp,0
je positive ;判断正数的溢出
negative:
neg bx ;bx是负数,求补
add bx,0 ;这条指令会改变psw,接下来判断符号位
jns overflow ;符号位是0,溢出
jmp L4 ;跳转到L4以16进制显示bx
positive:
add bx,0 ;bx是正数
js overflow ;符号位是1,溢出
L4:
mov cx,4
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
L5:
push cx
mov cl,4
rol bx,cl
mov dl,bl
and dl,0fh
cmp dl,9
ja L6
add dl,30h
jmp L7
L6:
add dl,37h
L7:
mov ah,2
int 21h
pop cx
loop L5
cmp cx,0
je exit
overflow:
lea dx,string
mov ah,9
int 21h
exit:
mov ah,4ch
int 21h
main endp
code ends
end main