标题:大家来写写汇编小玩意(三)
只看楼主
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:337
专家分:2462
注 册:2016-5-15
结帖率:100%
已结贴  问题点数:20 回复次数:25 
大家来写写汇编小玩意(三)
之前提了几个小题目,考的是写最短代码,这次来点别的,玩玩解题能力。

题目一:
先来百度:
考拉兹猜想,又称为3n+1猜想、角谷猜想、哈塞猜想、乌拉姆猜想或叙拉古猜想,是由日本数学家角谷静夫发现,是指对于每一个正整数,如果它是奇数,则对它乘3再加1,如果它是偶数,则对它除以2,如此循环,最终都能够得到1。
取一个数字。
如n = 6,根据上述公式,得出 6→3→10→5→16→8→4→2→1 。(步骤中最大的数是16,共有8个步骤)。
如n = 11,根据上述公式,得出 11→34→17→52→26→13→40→20→10→5→16→8→4→2→1。(步骤中最大的数是52,共有14个步骤)
考拉兹猜想称,任何正整数,经过上述计算步骤后,最终都会得到 1 。

题目来了。
输入:
输入需要验证角谷猜想的数n,0<n<1000000000(10亿),直到输入0或回车为止。

输出:
从数字n开始,依次输出经过变换后得到的每一个数字,数与数之间用“->”连接,直到输出1为止步。统计步骤中最大的数字m以及所需的步骤数x,然后在下一行输出如下引号中的信息:“Max is m and we need x steps.”。
对于步骤数的规定:我们约定,经过一次运算为1步,比如,在下面的输入样例中,从11到34就是第1步,如此循环,直到最后数字变成1为止。

比如:
11
输出:
11->34->17->52->26->13->40->20->10->5->16->8->4->2->1
Max is 52 and we need 14 steps.

其实逻辑挺简单的,这是我草草写的一个。



题目二:
1. 键盘输入的两个日期(日期为8位数的年月日),求出之间相差几天。
2. 在输入日期前要有提示信息(如:Input First Date / Input Second Date)

这题也很简单,重点是计算闰年,设定一个参考点....验证可用excel
一如既往,我也写了一个。



有趣兴可以写写,贴出代码,或者说说想法也可以。



搜索更多相关主题的帖子: 百度 数学家 正整数 最大的 日本 
2016-06-26 08:30
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:10 
感谢Valenciax为活跃本版所做的努力!
这两题要汇编做,已经很复杂了。估计没什么人接题,抽空我做下吧,不过第一题我只能用16位做,数据范围就是1-65536/3的范围(没有、也不知道怎么写32位汇编

能编个毛线衣吗?
2016-06-26 20:36
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:337
专家分:2462
注 册:2016-5-15
得分:0 
回复 2楼 wmf2014
谢谢班竹参与,国内汇编论坛一向冷清,反而国外比较热闹些,仍然有一群热心人写,他们许多人由dos写到win32和win64,x86写到sse4………

题一不会很复杂,64k内自然可以,至于如何读入大数,如何显示大数(甚至几百几千位),我会在接下的贴子跟大家分享,当然若有人写出来,那就更好了。

题二较难些,我会随后贴出代码和一些心得。



2016-06-26 23:02
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:396
帖 子:11713
专家分:43267
注 册:2006-5-13
得分:0 
围观,暂时没空参与讨论,先看看热闹。

活到老,学到老! http://www. E-mail:hu-jj@
2016-06-27 06:25
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:337
专家分:2462
注 册:2016-5-15
得分:0 
回复 2楼 wmf2014
班竹常提到的32BIT,其实之前写的一直是DOS的16BIT代码,只是偶然用到32BIT暂存器而已,题一写的也是DOS程式。一时起意,刚才用WIN32的控制台写了一个,用的是MASM32安装包里的MASM32 Editor编写,因为利用宏,输入输出借用了函数库,反而比DOS简单的多,更且可以用中文。
程序代码:
NLimit equ 999999999
include \masm32\include\masm32rt.inc
.stack 500h
.data
     Result dd 0,0
     myStep dd 0,0
     MaxValue dd 0,0
     output db "%I64i", 0 ;64bit format
     crtf db 10,13,0
.code
start:
     xor eax,eax
     lea edi,Result
     mov ecx,6
     rep stosd
     invoke atol, input(10,13,"角谷猜想 (1-999,999,999):") ;get input 
     cmp eax,1  ;is it 1
     jb quit ; less then , quit
     cmp eax,NLimit ; is it input limit ?
     ja start ;yes
     mov Result,eax ;save
next:  
     lea esi,Result  ;get last value address
     invoke crt_printf, offset output, qword ptr [esi] ;print it
     cmp Result,1  ;is it 1 ?
     jz next9  ;yes
     print ""  
     mov eax,Result ;get last value
     test eax,1  is it Even
     jz next2 ;yes , EVEN !
     ;-- ODD --
     add eax,Result 
     add eax,Result
     inc eax  ; x 3 + 1
     cmp eax,MaxValue ;最大值 ?
     jbe next4 ;no
     mov MaxValue,eax ;save it 最大值
     jmp short next4 
next2: ; -- EVEN
     shr eax,1  ; /2
next4:
     mov Result,eax  ;save it 
     inc myStep ;加步
     jmp short next ; looping....
next9:
     invoke crt_printf,addr crtf  ;other method to print 回车
     print "最大值 "
     lea si,MaxValue
     invoke crt_printf, offset output, qword ptr [esi] ;print最大值
     print ""
     lea si,myStep
     invoke crt_printf, offset output, qword ptr [esi] ;print 步
     print ""
     jmp start
quit:
     exit  ;結束
end start



[此贴子已经被作者于2016-6-27 10:06编辑过]

2016-06-27 07:53
zhulei1978
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:53
帖 子:1351
专家分:1200
注 册:2006-12-17
得分:0 

其实我就是改变社会风气,提高少女素质,刺激电影市道,提高年轻人内涵,玉树临风,风度翩翩的整蛊专家,我名叫古晶,英文名叫JingKoo!
2016-06-27 11:42
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:10 
我知道:所谓暂时没空参与=永远没空参与但有空围观!
好多人已过了有动力追求结果的年纪了,我也早过了。
作为写程序相当业余的我就处在这种状态:看到别人写得好的程序,会在心里酸酸地认为,这有什么了不起的,只要我下番功夫,肯定写得比他好。然后就永远不会下番功夫了。
5楼的代码这么简练?不需要考虑输入、输出,也不需要十进制-十六进制转换?我还在想怎么将键盘输入转变为16进制数呢。

能编个毛线衣吗?
2016-06-27 11:48
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:337
专家分:2462
注 册:2016-5-15
得分:0 
回复 7楼 wmf2014
对的,不用考虑太烦琐输入输出...
Masm32并不是微软官方出品,是一群有心人在维护,它们整合了masm32/64版,加了许多有用的宏,借用许多c标准函数库,比如上面5楼的atol、input和print等就是宏,atol是字符转long的意思,传回EAX的32bit值,一句宏相当于十数条汇编指令(我的dos版,光输入32值连容错代码就要三十多行),赶得上高阶语言的方便!

[此贴子已经被作者于2016-6-27 13:33编辑过]

2016-06-27 13:32
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:337
专家分:2462
注 册:2016-5-15
得分:0 
先发个子程序,若用int21h,ah=0AH读入字符串,这子程序能把它
转换成32bit数值传回,换言之,最多读到FFFFFFFFh,即4294967295

分两个版本
版本一只用16bit暂存器,由dx:ax传回
版本二用32bit暂存器,由EAX传回
使用方法,si指向输入缓冲,呼叫子程式即可
程序代码:

 lea dx,InputBuffer  ;指向输出缓冲
  mov ax,0c0ah  ;输入函数,先清空键盘缓冲
  int 21h

 ..

 ..

 ..

 lea si,InputBuffer + 2

 Call GetValue32 或 Call GetValue32x



16bit暂存器版
程序代码:
;--------------------------------------------------
;转值子程序,把输入的10进制文字转成16进制
;输入:ds:si数字字符串起点,以0dh或0结束
;输出:ds:ax=转换后的32进制值,cf=1表示有非数字字符
;若输入值少于65535,则dx=0
;--- 16bit暂存器版---------------------------------
GetValue32: 

 push bx

 push cx

 push si

 push di

 push bp

 xor cx,cx

 xor di,di

 xor dx,dx

 mov bx,10
d10:

 lodsb

 cmp al,0dh ;若以0d为结束符,启用这句,关闭下句
 ;cmp al,0  ;若以0为结束符,启用这句,关闭上句
 jz d20

 sub al,'0'

 cmp al,9

 jbe d15
d12:

 stc

 jmp short d99
d15:

 cbw

 mov bp,ax ;store to bp
 mov ax,cx ;get cx
 mul bx ;x 10
 mov cx,ax ;store to key hi
 mov ax,bp ;restore from bp
 xchg ax,di ;get key lo
 mul bx ;x 10
 xchg ax,di ;store to key lo
 add di,ax ;add low byte to key lo
 adc cx,dx ;add to key hi
 jnc d10

 jmp short d12
d20:

 mov dx,cx

 mov ax,di

 clc
d99:

 pop bp

 pop di

 pop si

 pop cx

 pop bx

 ret


32bit暂存器版
程序代码:
;--- 32bit暂存器版---------------------------------
;转值子程序,把输入的10进制文字转成16进制
;输入:ds:si数字字符串起点,以0dh或0结束
;输出:eax=转换后的32进制值,cf=1表示有非数字字符
;若希望由ds:ax传回,可加三句于ret之前
; mov edx,eax
; shr edx,16
; and eax,0000FFFFh
;--------------------------------------------------
.386
GetValue32X: 

 push ebx

 push edi

 xor ebx,ebx

 mov edi,10
GetV10:

 lodsb     ;指向起点
 and eax,000000ffh ;清除高bit,保留AL
 cmp al,0dh ;若以0d为结束符,启用这句,关闭下句
 ;cmp al,0  ;若以0为结束符,启用这句,关闭上句
 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
; mov edx,eax
; shr edx,16
; and eax,0000FFFFh
 ret



[此贴子已经被作者于2016-6-27 22:06编辑过]

2016-06-27 22:00
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:337
专家分:2462
注 册:2016-5-15
得分:0 
再发一个印出32位的代码

使用方法
 mov dx, yyyy
 mov ax, xxxx
 call  OutDec  ;印出dx:axh的 32值,若只输ax, dx必先清0
程序代码:
;-----以十进制输出DX:AX的32BIT值------
;输入 :dx=32bit高位,ax=32bit低位
;输出 :标准输出设备(屏幕)
;破坏暂存器:除dx,ax外,无
;注:若只输ax,dx先清0
;-------------------------------------
OutDec:     
    push bx
    push cx
    push si
    push bp
    xor cx,cx
    xchg bp,dx
    mov si,10      ;div by 10
    mov bx,30h  ;'0'
OutDec1:    
    or bp,bp    ;是否已除完高位?
    jz OutDec3  ;yes
    xchg bp,ax
    xor dx,dx
    div si   ; /10 ,利用除10取余法,逐步push入个位
    xchg bp,ax
    div si
    or dl,bl  ;转ascii
    push dx
    inc cx
    jmp short OutDec1
OutDec3:    
    xor dx,dx
    div si
    or dl,bl
    push dx
    inc cx
    or ax,ax  ; 是否已除完低位?
    jnz OutDec3  ;no
OutDec4:    ;到此,高低已除完! cx=有效个数
    pop ax   ;后入先出,分别pop回最前位,然后一直到个位
    int 29h  ;可改用int10h,ah=0eh,印出al, 或pop dx,用int21h,ah=2印出dl
    loop OutDec4
    pop bp
    pop si
    pop cx
    pop bx
    ret
;--------------------------------------


[此贴子已经被作者于2016-6-28 09:54编辑过]

2016-06-28 09:49



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-466366-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026226 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved