回复 18楼 wmf2014
很好,指令也很精简了
我也发一个dos版的,用的是32位暂存器(1-999999999),结果就是1楼的图,和5楼的不同,5楼是windows的控制台程式,只能在windows下运行,这个dos版在任何环境都可运行(win7/8 64bit需要dosbox或模拟器)
和楼上班竹的一样,这是com格式
Masm5.x要exe->com
Exe2bin xxx.exe
Masm6.1
ML /AT xxx.asm
程序代码:
NLimit equ 999999999
code segment
assume cs:code,ds:code,es:code,ss:code
org 100h
start:jmp short begin
InputBuffer db 10,0,10 dup (0)
DispStr db 10,13,'Input a number (1-999,999,999):$'
CurrentValue dd 0
Step dd 0
MaxValue dd 0
Dispstr1 db 10,13,'Max is ','$'
Dispstr2 db ' and we need ','$'
Dispstr3 db ' steps.','$'
CtrF db 10,13,'$'
begin:cld ;正向
Call GetUserInput ;输入子程序
;则对它乘3再加1,如果它是偶数,则对它除以2,如此循环,最终都能够得到1。
.386
cmp EAX,0
jz QuitX
mov CurrentValue,EAX
lea dx,CtrF
mov ah,9
int 21h
next:mov eax,CurrentValue
xor edx,edx
call print_dec
cmp eax,1
jz quit
push eax
mov al,26 ;->
int 29h
pop eax
test eax,1
jz next3 ;偶数
;奇数
next2:add CurrentValue,eax
add CurrentValue,eax
inc CurrentValue
mov eax,CurrentValue
cmp eax,MaxValue
jbe next4
mov MaxValue,eax
jmp short next4
next3: ;偶数
shr eax,1 ;/2
mov CurrentValue,eax
next4:inc Step
jmp short next
quit:lea dx,Dispstr1
call DispProc
mov eax,MaxValue
xor edx,edx
call print_dec
lea dx,Dispstr2
call DispProc
mov eax,Step
xor edx,edx
call print_dec
lea dx,Dispstr3
call DispProc
mov ah,7 ;暂停
int 21h
quitx:mov ah,4ch ;离开
int 21h
;--------------------------------------------------------------------------
;output EDX:EAX 输出64bit子程序 (0-18446744073709551615)
print_dec:pushad
xor ecx,ecx
xchg ebp,edx
mov esi,10 ;div by 10
mov ebx,30h
print_dec1:or ebp,ebp
jz print_dec3
xchg ebp,eax
xor edx,edx
div esi
xchg ebp,eax
div esi
or dl,bl
push dx
inc ecx
jmp short print_dec1
print_dec3:xor edx,edx
div esi
or dl,bl
push dx
inc ecx
or eax,eax
jnz print_dec3
print_dec4:pop ax
int 29h
loop print_dec4
popad
ret
;--------------------------------------------------------------------------
;转值子程序,把输入的10进制文字转成16进制
;输入:ds:si数字字符串起点,以0dh结束
;输出:eax=转换后的16进制值(32bit),cf=1表示有非数字字符
GetValue:push ebx
push edi
xor ebx,ebx
mov edi,10
GetV10:lodsb ;指向起点
and eax,000000ffh ;清除高bit,保留AL
cmp al,0dh ;回车?
;cmp al,0 ;-----zero
jz Getvx
sub al,'0'
cmp al,9
ja Getvy
xchg ebx,eax ;交换
mul edi
add ebx,eax ;累加
jmp short GetV10
Getvx:mov eax,ebx ;ascii转值后由eax转回
clc ;成功cf=0
jmp short Getvz
Getvy:stc ;错误 cf=1
Getvz:pop edi
pop ebx
ret
;-------------------------------------------------------------------
GetUserInput: mov ah,9
lea dx,DispStr ;提示
int 21h
lea dx,InputBuffer ;指向输出缓冲
mov ax,0c0ah ;输入函数,先清空键盘缓冲
int 21h
lea si,InputBuffer + 2
mov cx,0
mov cl,[si-1] ;取实际输入数
jcxz GetUx ;无输入
Call GetValue ;取值子程序,ax传回该值,cf=1表示错误,可能输入非数字
jc GetUserInput ;输入错误,非数字
cmp eax,NLimit ;999999999 ?
ja GetUserInput
ret
GetUx:xor eax,eax
ret
;-------------------------------------------------------------------
DispProc:mov ah,9
int 21h
ret
;-------------------------------------------------------------------
CODE ENDS
END START
[此贴子已经被作者于2016-6-30 13:06编辑过]