; 输入的五位数字,第一位为符号位,当符号位为0时为正数,否则为负数
; 后四位为参数计算的数字,输出结果同上
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
input1 db 'Input first number! ','$'
input2 db 'Input second number! ','$'
result db 'result is : ','$'
; 21号中断10号例程,存放输入数据
add1 db 6 ; 缓冲区最大容量
db ? ; 实际上接收字符的个数,不包括最后的回车
db 6 dup (?) ; 存放输入的字符,回车结尾
add2 db 6
db ?
db 6 dup (?)
num dw ? ; 存放中间结果
sign db ? ; 两个数和的符号位
sum dw 10 dup (?) ; 两个数的和
datasg ends
stacksg segment
stacksg ends
codesg segment
start: mov ax,datasg
mov ds,ax
lea dx,input1
mov ah,9
int 21h
; 读取第一个加数
mov dx,offset add1
mov ah,10
int 21h
; 取光标位置,ah为行,al为列
mov ah,3
mov bh,0
int 10h
; 设置光标位置
mov ah,2
mov bh,0
inc dh
mov dl,0
int 10h
lea dx,input2
mov ah,9
int 21h
; 读取第二个加数
mov dx,offset add2
mov ah,10
int 21h
; 取光标位置,ah为行,al为列
mov ah,3
mov bh,0
int 10h
; 设置光标位置
mov ah,2
mov bh,0
inc dh
mov dl,0
int 10h
lea bx,add1
mov ax,[bx+1]
mov ah,0
dec ax ; 除去符号位,得到数字个数
push ax ; 压入字符数量
add bx,3
push bx ; 压入字符串首地址
call DeciToBina
lea bx,add1
mov dl,[bx+2] ; 取输入的数字的符号位
cmp dl,'0'
jz posi1
neg ax ; 符号位不为0,则表示负数,所以求补得到负数
posi1:
lea bx,num
mov [bx],ax ; 保存第一个数
lea bx,add2
mov ax,[bx+1]
mov ah,0
dec ax
push ax ; 压入字符数量
add bx,3
push bx ; 压入字符串首地址
call DeciToBina
lea bx,add2
mov dl,[bx+2]
cmp dl,'0'
jz posi2
neg ax
posi2:
lea bx,num
add [bx],ax ; 保存两个数相加的结果
lea dx,result
mov ah,9
int 21h
lea bx,num
mov ax,[bx] ; 取出两个数的和
push ax ; 保存一个备份
; 测试结果的符号位
and ax,1000000000000000b ; 取最高位
neg ax
sbb ax,ax
neg ax ; ax的值是0或1
add ax,30h ; 转为0或1的ascii码
lea bx,sign
mov [bx],al ; 存入符号位
pop ax ; 取出备份
cmp byte ptr [bx],30h ; 测试结果是否为正数
jz posi
neg ax ; 不为正,则求补取绝对值
posi:
push ax ; 压入第二个参数,即待转换的十六进制数的绝对值
lea di,sum
push di ; 压入第一个参数,接收结果的缓冲区
call BinaToDeci
lea dx,sign
mov ah,9
int 21h
mov ax,4c00h
int 21h
; ***********************************************************************
; 作用:将十六进制数,转为十进制字符,用以输出
; 形式:void BinaToDeci( [buff], int ),从右向左依次压入堆栈
; 参数1:第一个参数 [buff]:接收结果的缓冲区地址
; 参数2:第二个参数int :待转换的十六进制数字
; 返回值:无,直接保存到内存中
; ***********************************************************************
BinaToDeci proc
push bp
mov bp,sp
push ax
push bx
push cx
push dx
mov cx,0 ; 初始化计数器,记录循环次数,即十进制数的位数
mov ax,[bp+6] ; 取出传入的待转换十六进制数,段内调用只加6,段间调用加8
; 计算出十进制各位数字,并保存到堆栈
bina_next:
xor dx,dx
mov bx,10
div bx
push dx
inc cx
cmp ax,0
jz bina_end
jmp bina_next
bina_end:
mov bx,[bp+4] ; 取出保存十进制数的缓冲区首地址
; 将十进制的各个位数转换成ascii码,并存入指定的内存区域
bina_next2:
pop ax
add ax,30h
mov byte ptr [bx],al
inc bx
loop bina_next2
; 字符串以'$'结尾,用以调用21号中段的9号例程
mov byte ptr [bx],'$'
pop dx
pop cx
pop bx
pop ax
mov sp,bp
pop bp
ret 4
BinaToDeci endp
; ***********************************************************************
; ***********************************************************************
; 作用:将十进制字符,转换为十六进制数,用以计算
; 形式:void DeciToBina( [buff], int ),从右向左依次压入堆栈
; 参数1:第一个参数 [buff]:放置十进制数字字符串的缓冲区的首地址
; 参数2:第二个参数int :十进制字符串的字符个数
; 返回值:十六进制的数字
; ***********************************************************************
DeciToBina proc
push bp
mov bp,sp
push bx
push cx
push dx
push si
mov bx,[bp+4] ; 取放置十进制字符串缓冲区的首地址
mov cx,[bp+6] ; 十进制数字字符串的字符个数
xor ax,ax
; 将ascii码还原为数字,并保存到堆栈
deci_next:
mov al,byte ptr [bx] ; 依次取缓冲区内的字符
sub al,30h
push ax
inc bx
loop deci_next
mov cx,[bp+6] ; 再次获得字符的个数
xor ax,ax
xor dx,dx
mov bx,1 ; 用作乘数
xor si,si
; 各位相乘然后累加获得十六进制数值
; 结果=个位*1+十位*10+百位*100+千位*1000
deci_next1:
pop ax ; 取出数字
mul bx ; 相乘
add si,ax ; 累加结果
; 计算下次相乘时的乘数
mov ax,bx
mov bx,10
mul bx
mov bx,ax
loop deci_next1
; 将结果存入ax,为返回值
mov ax,si
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret 4
DeciToBina endp
; ***********************************************************************
codesg ends
end start
=====================================================
masm5测试通过
试一下要多久,现在开始,阿门。。。
emu8086编译测试通过,附运行测试截图
====================================
; multi-segment executable file template.
data segment
; add your data here!
oper1 dw 0000h
;oper2
sum db 5 dup(00h)
altemp db 00h
message1 db 'The first number :','$'
message2 db 'The sec0nd number :','$'
message3 db 'The sum of them is:','$'
message4 db 0dh,0ah,'The input number begins with - or + and end with enter or four bits','$'
message5 db 'Press ESC to exit or any other key to contiune','$'
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
; add your code here
;inputoper1:
call newlinebegin
lea dx, message1
mov ah, 09h
int 21h ; output string at ds:dx
call readsign; the sign would be in dl(zero label '-';nzero label '+')
call readabsval; the asbval would be in bx
cmp dl,00h
jz negative1
mov oper1,bx
jmp inputoper2
negative1:
xor ax,ax
sub ax,bx
mov oper1,ax
inputoper2:
call newlinebegin
lea dx, message2
mov ah, 09h
int 21h ; output string at ds:dx
call readsign; the sign would be in dl(zero label '-';nzero label '+')
call readabsval; the asbval would be in bx
cmp dl,00h
jz negative2
mov ax,bx
jmp out_result
negative2:
xor ax,ax
sub ax,bx
out_result:
push ax
call newlinebegin
lea dx, message3
mov ah, 09h
int 21h ; output string at ds:dx
pop ax
;ax=oper2
mov bx,oper1 ;bx=oper1
add ax,bx ;ax=sum of oper1 and oper2
call outresult;
call newlinebegin
lea dx, message5
mov ah, 09h
int 21h ; output string at ds:dx
mov ah,08h
int 21h
cmp al,1bh
jz exit
call newlinebegin
lea dx, message4
mov ah, 09h
int 21h ; output string at ds:dx
jmp start
exit:
mov ax, 4c00h ; exit to operating system.
int 21h
;---------------------------------------
;call readabsval
readabsval proc near
;in: none
;out: bx=the operator
push ax
push cx
push dx
xor bx,bx
mov cx,04h
max4bcd:call readchar_numorenter
cmp al,0dh
jz readabsvalout
mov altemp,al
mov ax,bx
mov bx,0ah
mul bx
mov bx,ax
mov al,altemp
xor ah,ah
add bx,ax
loop max4bcd
readabsvalout:
pop dx
pop cx
pop ax
ret
readabsval endp
;---------------------------------------
;call readchar_numorenter
readchar_numorenter proc near
;in: none
;out: al=the numval or enter
push dx
readchar_numorenterredo:mov ah,08h
int 21h
cmp al,0dh
jz readchar_numorenterout
cmp al,30h
jl readchar_numorenterredo
cmp al,39h
jg readchar_numorenterredo
mov ah,02h
mov dl,al
int 21h
sub ax,0230h
readchar_numorenterout:
pop dx
ret
readchar_numorenter endp
;---------------------------------------
;call readsign
readsign proc near
;in: none
;out: dl= zero - or nzero +
push ax
rereadsign:
mov ah,08h
int 21h
cmp al,2bh
jz oppsign
cmp al,2dh
jz negsign
jmp rereadsign
negsign:
mov dl,2dh
mov ah,02h
int 21h
xor dl,dl
pop ax
ret
oppsign:
mov dl,2bh
mov ah,02h
int 21h
mov dl,01h
pop ax
ret
readsign endp
;---------------------------------------
;call outresult;
outresult proc near
mov bx,ax
js outnegtive
mov dl,2bh
jmp outresultval
outnegtive:
mov dl,2dh
neg bx
outresultval:
;outsign
mov ah,02h
int 21h
;out absval
lea di,sum
add di,04h
mov ax,bx
mov bx,0ah
mov cx,05h
sent: xor dx,dx
div bx
add dl,30h
mov [di], dl
dec di
loop sent
lea si,sum
mov bl,00h;as a flat of head zero
mov ah,02h
mov cx,05h
out_Dnum: mov dl,[si]
cmp dl,30h
jnz outnum
test bl,01h
jnz outnum
cmp cx,01h
jz outnum
jmp outvalcontinue
outnum:mov bl,01h
int 21h
outvalcontinue: inc si
loop out_Dnum
ret
outresult endp
;---------------------------------------
;call newlinebegin
newlinebegin proc near
push ax
push dx
mov ah,02h
mov dl,0dh
int 21h
mov dl,0ah
int 21h
pop dx
pop ax
ret
newlinebegin endp
ends
end start ; set entry point and stop the assembler.
====================================
masm5.0测试通过版本
data segment
oper1 dw 0000h
sum db 5 dup(00h)
altemp db 00h
message1 db 'The first number :','$'
message2 db 'The sec0nd number :','$'
message3 db 'The sum of them is:','$'
message4 db 0dh,0ah,'The input number begins with - or + and end with enter or four bits','$'
message5 db 'Press ESC to exit or any other key to contiune','$'
data ends
stack segment
dw 128 dup(0)
stack ends
code segment
assume cs:code,ds:data,ss:stack,es:data
start:
mov ax, data
mov ds, ax
mov es, ax
call newlinebegin
lea dx, message1
mov ah, 09h
int 21h
call readsign
call readabsval
cmp dl,00h
jz negative1
mov oper1,bx
jmp inputoper2
negative1:
xor ax,ax
sub ax,bx
mov oper1,ax
inputoper2:
call newlinebegin
lea dx, message2
mov ah, 09h
int 21h
call readsign
call readabsval
cmp dl,00h
jz negative2
mov ax,bx
jmp out_result
negative2:
xor ax,ax
sub ax,bx
out_result:
push ax
call newlinebegin
lea dx, message3
mov ah, 09h
int 21h ; output string at ds:dx
pop ax
;ax=oper2
mov bx,oper1 ;bx=oper1
add ax,bx ;ax=sum of oper1 and oper2
call outresult;
call newlinebegin
lea dx, message5
mov ah, 09h
int 21h ; output string at ds:dx
mov ah,08h
int 21h
cmp al,1bh
jz exit
call newlinebegin
lea dx, message4
mov ah, 09h
int 21h ; output string at ds:dx
jmp start
exit:
mov ax, 4c00h ; exit to operating system.
int 21h
;---------------------------------------
;call readabsval
readabsval proc near
;in: none
;out: bx=the operator
push ax
push cx
push dx
xor bx,bx
mov cx,04h
max4bcd:call readchar_numorenter
cmp al,0dh
jz readabsvalout
mov altemp,al
mov ax,bx
mov bx,0ah
mul bx
mov bx,ax
mov al,altemp
xor ah,ah
add bx,ax
loop max4bcd
readabsvalout:
pop dx
pop cx
pop ax
ret
readabsval endp
;---------------------------------------
;call readchar_numorenter
readchar_numorenter proc near
;in: none
;out: al=the numval or enter
push dx
readchar_numorenterredo:mov ah,08h
int 21h
cmp al,0dh
jz readchar_numorenterout
cmp al,30h
jl readchar_numorenterredo
cmp al,39h
jg readchar_numorenterredo
mov ah,02h
mov dl,al
int 21h
sub ax,0230h
readchar_numorenterout:
pop dx
ret
readchar_numorenter endp
;---------------------------------------
;call readsign
readsign proc near
;in: none
;out: dl= zero - or nzero +
push ax
rereadsign:
mov ah,08h
int 21h
cmp al,2bh
jz oppsign
cmp al,2dh
jz negsign
jmp rereadsign
negsign:
mov dl,2dh
mov ah,02h
int 21h
xor dl,dl
pop ax
ret
oppsign:
mov dl,2bh
mov ah,02h
int 21h
mov dl,01h
pop ax
ret
readsign endp
;---------------------------------------
;call outresult;
outresult proc near
mov bx,ax
js outnegtive
mov dl,2bh
jmp outresultval
outnegtive:
mov dl,2dh
neg bx
outresultval:
;outsign
mov ah,02h
int 21h
;out absval
lea di,sum
add di,04h
mov ax,bx
mov bx,0ah
mov cx,05h
sent: xor dx,dx
div bx
add dl,30h
mov [di], dl
dec di
loop sent
lea si,sum
mov bl,00h;as a flat of head zero
mov ah,02h
mov cx,05h
out_Dnum: mov dl,[si]
cmp dl,30h
jnz outnum
test bl,01h
jnz outnum
cmp cx,01h
jz outnum
jmp outvalcontinue
outnum:mov bl,01h
int 21h
outvalcontinue: inc si
loop out_Dnum
ret
outresult endp
;---------------------------------------
;call newlinebegin
newlinebegin proc near
push ax
push dx
mov ah,02h
mov dl,0dh
int 21h
mov dl,0ah
int 21h
pop dx
pop ax
ret
newlinebegin endp
code ends
end start ; set entry point and stop the assembler.
=======================================
测试运行截图:
;编写一个程序,能从键盘读入两个5位十进制数(1位符号位和4位数值位),并将这两个;
十进制数分别转换为二进制数,然后求其和,再将和以十进制形式进行显示。
;
;要求:提示从键盘输入第一个数,按回车完成输入;然后提示从键盘输入第二个数,按回
;车完成输入。然后显示输入的两个数的和。能够从键盘输入-9999~+9999之间的数值。
;相互转化那个功能要用两个子程序(即十进制变二进制、二进制变十进制)完成,
;本人就是在这个子程序这里,不太会多位数字的转换,.....急求!!!!!!!!
;用MASM5.0编译通过
data segment
S0 DB 0DH,0AH,'
s1 db 0dh,0ah,'Enter first NUM: $'
s2 db 0dh,0ah,'Enter second NUM: $'
S3 DB 0DH,0AH,24H
ADD_S DB ' (+) $'
D1 DW 0 ;输入的第一个数
D2 DW 0 ;输入的第二个数
D3 DW 0 ;两数相加的结果
T DW 0 ;输入数字的临时存放位置
FU DB 0 ;正负号,0为正 1为负
COUNT DB 0 ;数位计数器 (限于4位)
data ends
code segment
assume cs:code, ds:data
main proc far
start:
push ds
xor ax,ax
push ax
mov ax,data
mov ds,ax
;-------------------------
MOV AH,9
MOV DX,OFFSET S0
INT 21H
AGAIN:
mov ah,09
mov dx ,offset s1
int 21h
call input
MOV AX,T
MOV D1,AX
mov ah,09
mov dx ,offset s2
int 21h
call input
MOV AX,T
MOV D2,AX
ADD AX,D1
MOV D3,AX
mov ah,09
mov dx ,offset s3
int 21h
MOV AX,D1
ADD AX,D2
MOV AX,D1
CALL DISP
MOV AH,9
MOV DX,OFFSET ADD_S
INT 21H
MOV AX,D2
CALL DISP
MOV AH,2
MOV DL,'='
INT 21H
MOV AX,D3
CALL DISP
;-------------------------
JMP AGAIN
ret
main endp
;=============
input proc near
mov ax,0 ;初始化
mov T,AX
MOV FU,AL
MOV COUNT,AL
;
NEXT:
MOV AH,08 ;不回显输入(可CTRL+C中断)
INT 21H
CMP AL,0DH
JNZ N1
JMP SAVE ;回车输入完毕
N1:
MOV AH, COUNT ;是否输入了4位数
CMP AH,4
JE NEXT ;已达4位,不允许再输入
CMP AL,'-'
JNE PD0_9
MOV AH,FU ;检测到输入'-',检查先前是否已输入过
CMP AH,0
JNE NEXT ;FU=0 未输入'-' ,FU=1 已输入'-'
MOV BX,T ;如果前面已输入数字位,则不允许在数字中间再输入"-"
CMP BX,0
JA next
FU_INC:
INC FU ;置FU=1 表示已输入'-'
MOV AH,2
MOV DL,AL
INT 21H
JMP NEXT
PD0_9:
CMP AL,'0' ;只允许输入0-9
JB NEXT
CMP AL,'9'
JA NEXT
PUSH AX
MOV DL,AL ;显示输入的0-9
MOV AH,2
INT 21H
POP AX
SUB AL,30H ;以下: T <= [将已输入在T中的数 * 10d + 现在输入的数]
PUSH AX
MOV AX,T
MOV BX,10
MUL BX
POP BX
MOV BH,0
ADD AX,BX
MOV T,AX
INC COUNT ;输入位数计数器+1
JMP NEXT
SAVE: ;保存输入的数据
MOV BX,T
MOV AL,FU
CMP AL,0
JE SAVE1
NEG BX ;若输入的是负数,则求补
SAVE1:
MOV T,BX
RET
input ENDP
;================
DISP PROC NEAR ;以10进制显示数字
TEST AX,8000H ;高位为1是负数,否则为正
JZ ZZ
NEG AX ;数字为负,求补
PUSH AX
MOV AH,2
MOV DL,'-' ;显示"-"
INT 21H
POP AX
ZZ: ;数字为正
MOV DX,0
MOV BX,10000 ;转换成10进制的万位数值
DIV BX
PUSH DX
MOV AH,2
MOV DL,AL
ADD DL,30H
INT 21H
POP AX
MOV DX,0
MOV BX,1000 ;转换成10进制的千位数值
DIV BX
PUSH DX
MOV AH,2
MOV DL,AL
ADD DL,30H
INT 21H
POP AX
MOV BL,100 ;转换成10进制的百位数值
DIV BL
PUSH AX
MOV DL,AL
ADD DL,30H
MOV AH,2
INT 21H
POP AX
MOV AL,AH
MOV AH,0
MOV DL,10 ;转换成10进制的十位和个位数值
DIV DL
ADD AX,3030H
PUSH AX
MOV DL,AL
MOV AH,2
INT 21H
POP DX
MOV DL,DH
MOV AH,2
INT 21H
RET
DISP ENDP
;================
code ends
end start
呵呵,看到这里想起了以前学校搞个这些东东,也搞出来了。说句实话搞这些真的一点都没用!
除非毕业后你是搞X86asm,搞单片机的最好学习单片机方面的知识,比这实用多。