| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 9831 人关注过本帖
标题:大家来写写汇编小玩意(三)
只看楼主 加入收藏
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
回复 9楼 Valenciax
咦?其实就是atoi函数,这就简单了。
我想复杂了,还在考虑将输入转换为bcd码,还是不是要用什么aam、aad进行asc码调整,想到这些指令从未用过(其实以前写汇编算术运算最多无符号加减),就迟迟没动手了
最近真的事多,体制内的单位总是忙着搞半年度材料,很不幸地我就是那个写材料的最底层的那个。无暇写这些作业,容后再说了~~~~

能编个毛线衣吗?
2016-06-28 13:01
zhulei1978
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:53
帖 子:1351
专家分:1200
注 册:2006-12-17
收藏
得分:0 
这是作业吗,没人给你布置作业啊

其实我就是改变社会风气,提高少女素质,刺激电影市道,提高年轻人内涵,玉树临风,风度翩翩的整蛊专家,我名叫古晶,英文名叫JingKoo!
2016-06-28 15:24
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
题一有了9/10楼的输入/输出子程序,写代码就不是难事,再不明白可参考5楼的写法。

接下来说说题二
重点是解决闰年的判断,先来一段百度
西元年分除以400可整除,为闰年。
西元年分除以4可整除但除以100不可整除,为闰年。
西元年分除以4不可整除,为平年。
西元年分除以100可整除但除以400不可整除,为平年

好了,有了定义,下面我写了一段判断闰年的子程序。

用法:
MOV AX,YEAR (待查的年份)
CALL LeapYear

传回AX=1(闰年)
传回AX=0(非闰年)

程序代码:
LeapYear:  ;輸入AX=年份,輸出AX=1(閏年),AX=0(非閏年)
 push bx

 push dx

 push si

 mov si,ax

 mov bx,400 ;年份除以400餘數等于零,為閏年
 mov dx,0

 div bx

 or dx,dx ;是否0 
 jz last ;餘數為零,直接輸出閏年 
 mov dx,0 

 mov bx,4 ;除以400餘數不等于0,進行除以4餘數是否等0的判斷
 mov ax,si 

 div bx

 or dx,dx  ;是否0
 jz ok ;除以四餘數等于0,跳往除以100餘數是否等0的判斷
over:
;除以四餘數不等于0,則不為閏年,結束 
 mov ax,0

 jmp nil

ok: mov bx,100 ;除以100餘數為零,則不為閏年,餘數不為零,則為閏年
 mov dx,0 

 mov ax,si 

 div bx

 or dx,dx ;是否0
 jz over
last:

 mov ax,1
nil:

 pop si

 pop dx

 pop bx

 ret


然后是2月的28/29问题
我们先建立一个月份的天数阵列
monthday dw 31,28,31,30,31,30,31,31,30,31,30,31 ;月份天数

这其中,除了二月都是恒定的,但可以根据使用者输入的年份去加或不加二月。
若是闰年,二月的28加1,否则不加。
拿这个表格,还可以判断使用者输入的日期是否合法,若输入2015/2/29,查知该年2月是28天,不符!
若输入2016/2/29,查知该年2月是29天,通行!

接下来,我们定义一个参考点,就1000年吧,若输入2016/2/29。
计算方法是:
1.
定义一个双字的总年份 TOTALYEAR DD 0
由年份1000起,AX=年份,呼叫LeapYear子程序得知该年是否闰年,
是则TOTALYEAR + 366, 否则 + 365
年份+1,回到1再加,直到输入年份的前一年,2015。
2.
计算该年的总天数。
由输入月份的前一月加起,根据表格monthday的该月天数加,直加到1月,再加上输入日期,
就是该年的总天数。
3.
该年的总天数加上1项的天数就是[使用者输入年月日]和1000/1/1相差的天数。
4.
将使用者输入的两个日期相减,就是两个日期的[相差值]。
5.
印出



原理说完了,有了LeapYear子程序,还怕写不出来?

2016-06-29 07:37
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11771
专家分:43421
注 册:2006-5-13
收藏
得分:0 
以下是引用zhulei1978在2016-6-28 15:24:14的发言:

这是作业吗,没人给你布置作业啊

这是自己给自己布置的作业,一则活跃论坛,二则练练手,开拓思路。

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2016-06-29 07:38
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 14楼 hu9jj
刚贴了点东西就看见班竹回话了,早上好
2016-06-29 07:40
zhulei1978
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:53
帖 子:1351
专家分:1200
注 册:2006-12-17
收藏
得分:0 
Valanciax好积极啊,希望大家都能提高汇编水平

其实我就是改变社会风气,提高少女素质,刺激电影市道,提高年轻人内涵,玉树临风,风度翩翩的整蛊专家,我名叫古晶,英文名叫JingKoo!
2016-06-29 11:09
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11771
专家分:43421
注 册:2006-5-13
收藏
得分:0 
以下是引用Valenciax在2016-6-29 07:40:58的发言:

刚贴了点东西就看见班竹回话了,早上好

我是蜻蜓点水,早上浏览一下就退出了,晚上再浏览一次,每次的时间不超过半小时,所以没及时回复。现在只好回复:晚安!

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2016-06-29 21:17
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
总算有点空了,交第一题作业。
未做全面测试,数据范围只能为1-21845,做32位的或多位的烧脑!另关于第二题:我曾经在c里用一行算术代码完成获取指定月份天数,在汇编里可能就复杂多了,空下来再弄吧!
程序代码:
    code segment
    assume cs:code,ds:code,es:code,ss:code
    org 100h
start:    mov dx,offset buf1
    mov si,offset buf1+2
    mov ax,0c0ah
slp1:    int 21h
    mov ah,2
    mov dl,10
    int 21h
    call atoi
    or ax,ax
    jz slp2
    cmp ax,21845
    ja slp2              ;数据合法性判断
slp5:    cmp ax,max
    jb slp6
    mov max,ax           ;得到最大数
slp6:    mov bx,ax            ;空出ax寄存器调int21用
    call hexdec          ;显示数据
    cmp bx,1
    jz slp3              ;最终数据是1,完成
    inc word ptr step    ;操作步数增1
    mov dx,offset disp5
    mov ah,9
    int 21h              ;显示->2361545863 余金平
    mov cx,1
    mov ax,bx
    and cx,bx
    jz slp4              ;转到对偶数的处理
    mov cx,3
    mul cx
    inc ax
    jmp slp5             ;*3+1
slp4:    shr ax,1
    jmp slp5             ;/2
slp3:    mov dx,offset disp6
    mov ah,9
    int 21h              ;回车换行
    mov dx,offset disp2
    int 21h              ;Max is
    mov ax,max
    call hexdec          ;显示最大数
    mov ah,9
    mov dx,offset disp3
    int 21h              ;and we need
    mov ax,step
    call hexdec          ;显示总步数
    mov ah,9
    mov dx,offset disp4
    int 21h              ;steps.
    jmp slp7
slp2:    mov ah,9
    mov dx,offset disp1  ;显示数据错误
    int 21h
slp7:    mov ax,4c00h
    int 21h
atoi:    ;本函数将asc串转换为16位int数,ds:si为asc串首,非数字转换结束,结果在ax中返回
    push si
    push bx
    push cx
    push dx
    xor cx,cx
    mov bx,10
ailp2:    mov ax,cx
    mul bx
    jc ailp1
    mov dx,ax
    xor ax,ax
    lodsb
    sub al,'0'
    cmp al,9
    ja ailp1
    mov cx,dx
    add cx,ax
    jmp ailp2
ailp1:    mov ax,cx
    pop dx
    pop cx
    pop bx
    pop si
    ret    
hexdec:    ;本函数将16进制数用十进制数形式显示出来,待显示的数在ax中
    push bx
    push cx
    push dx
    xor cx,cx
    mov bx,10
hdlp1:    xor dx,dx
    div bx
    add dl,'0'
    push dx
    inc cx
    or ax,ax
    jnz hdlp1
    mov ah,2
hdlp2:    pop dx
    int 21h
    loop hdlp2
    pop dx
    pop cx
    pop bx
    ret
    buf1 db 20,0,20 dup(0)
    max dw 0
    step dw 0
    disp1 db " Input Error! $"
    disp2 db " Max is $"
    disp3 db " and we need $"
    disp4 db " steps.",13,10,'$'
    disp5 db "->$"
    disp6 db 13,10,'$'
    code ends
    end start

图片附件: 游客没有浏览图片的权限,请 登录注册

能编个毛线衣吗?
2016-06-30 11:47
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 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编辑过]

2016-06-30 12:56
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
我的获取某月天数的函数,利用int 21h返回错误的特性,无需计算闰年,无需建立月份天数表(早期我用vb写数据库应用时用过这方法,也是利用错误捕获获得某月天数的):
程序代码:
redate:    ;本函数返回某年某月份天数,结果在ax中,调用bx:年,al:月
    push bx
    push cx
    push dx
    push ax
    mov ah,2ah
    int 21h
    pop ax
    push cx
    push dx           ;保存当前日期
    mov ah,2bh
    mov cx,bx
    mov dh,al
    mov dl,32
ymdlp1:    dec dl
    int 21h
    or al,al
    jnz ymdlp1
    mov bl,dl
    pop dx
    pop cx
    int 21h           ;恢复当前日期
    xor ax,ax
    mov al,bl
    pop dx
    pop cx
    pop bx
    ret

能编个毛线衣吗?
2016-06-30 16:59
快速回复:大家来写写汇编小玩意(三)
数据加载中...
 
   



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

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