| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7503 人关注过本帖
标题:大家来写写汇编小玩意
只看楼主 加入收藏
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:18 
大家来写写汇编小玩意
汇编一向是小众玩意,普遍认为写复杂程式挺烦,版面冷清是常态。
好吧,大的不想写,不如写写小巧东西活活脑筋吧!

出两个简单题目,看谁写得最短。

题目一.
用最短代码写出编印256个ASCII码的程式
ASCII就是美国标准信息交换代码,是基于拉丁字母的一套电脑编码系统(百度)
常见的0,1234...ABCDabcd..!@#$%^&也包含在内。
我写的一个用了7个bytes,未必是最短,等待你的写一个更短的,当然长些也不妨,
不同编码自有不同的逻辑技巧,他山之石可以攻玉。
图片附件: 游客没有浏览图片的权限,请 登录注册


题目二
用最短代码编印
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
就是数字0..9 , 小写的a..z 和大写的A..Z
我写的一个用了26个bytes,或许还有优化空间!
图片附件: 游客没有浏览图片的权限,请 登录注册


想了一下,原来仍有缩小空间,这个用了24bytes

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


代码我会稍后贴出,大家来动动脑,贴出代码或结果,多交流才会进步,不是吗?

[此贴子已经被作者于2016-6-9 11:02编辑过]

搜索更多相关主题的帖子: 拉丁字母 百度 美国 技巧 
2016-06-09 09:53
zhulei1978
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:53
帖 子:1351
专家分:1200
注 册:2006-12-17
收藏
得分:0 
以前都写过

其实我就是改变社会风气,提高少女素质,刺激电影市道,提高年轻人内涵,玉树临风,风度翩翩的整蛊专家,我名叫古晶,英文名叫JingKoo!
2016-06-09 12:17
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11771
专家分:43421
注 册:2006-5-13
收藏
得分:0 
支持活跃气氛!

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2016-06-09 21:12
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
楼上两位班竹有空可以玩玩。

既然暂时没人插足,先在这里贴一个正儿八经的看看,然后一步步走下去。

程序代码:
CODE segment
assume  cs:CODE,ds:CODE,es:CODE,ss:CODE
  org 100h
start:

 mov dl,'0'

 mov ah,2

 mov cx,10
s10:

 int 21h 

 inc dl

 loop s10

 

 mov dl,'a'

 mov cx,26
s20:

 int 21h 

 inc dl

 loop s20


 mov dl,'A'

 mov cx,26
s30:

 int 21h 

 inc dl

 loop s30


 mov ah,4ch

 int 21h

CODE ENDS
END START

;39bytes

程式要小,EXE是不可行的,光PE档头就占512bytes,所以要把它变成COM格式。
COM没有档头,是直接内存的bin影像,WIN764bit以上的dos模式已经不支援运行
这些16bit程式,但仍有dosbox或模拟器可用。

COM不常见,但若要写boot起动代码,把它转换成没有档头的COM或bin是必要的。
上面这段程式编译成com,若在masm6.x
ML /AT numx.asm

若在masm5.x,步骤如下
masm numx.asm
link numx.asm
exe2bin numx.exe

好了,把编译完成,看一看,39bytes,嗯,正常写法就是这个大小。

或许有人会说,现在什么年代了,Windows都64bit,内存8G还嫌小,还在意省这么几个bytes?
我会这样回答,现在什么年代了,高铁都能跑数百里/小时,却有人喜欢踏数百公里的自行车,
苦哈哈的爬上珠穆朗玛峰,为了100公尺跑10秒内练它三五七年....

对了,就是挑战,或者游戏,写代码也可以是游戏是挑战,不当它是功课写起来起劲得多。

换一个角度看,比如我们要在一个运行中的程式插入一段代码,好不容易找到一块
50bytes的空间,你却在那里写正儿八经的标准代码,胖胖的size如下插得下那么稀缺挤逼的空间?
不想方计法把程式写得小是不行的。


回到我们这段39bytes的胖代码,如何缩小?
我们想到回圈,并把印字节改为int 10h的0Eh函数,返回dos改用int20h。

程序代码:
;31bytes
CODE segment
assume  cs:CODE,ds:CODE,es:CODE,ss:CODE
  org 100h
start:

 mov cx,10

 mov bl,2

 mov al,'0'

 mov ah,0eh
s10:

 int 10h

 inc al

 loop s10

 dec bl

 mov al,'A'

 js quit   ;-1
 jz s30

 mov al,'a'
s30:

 mov cl,26

 jmp short s10 
quit:

 int 20h

 
CODE ENDS
END START

这样一改,一下子缩小到31bytes,离姥姥家不远了。

收到的鲜花
  • hu9jj2016-06-10 08:35 送鲜花  50朵   附言:精神可嘉,支持!
  • zhulei19782016-06-10 12:37 送鲜花  50朵   附言:我很赞同
2016-06-10 08:14
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:10 
第一个我7个字节做不到,用debug写的,得11个字节,还要向楼主学习!debug里代码如下:
0100:mov ax,0e00
0103:int 10
0105:inc al
0107:jnz 0103
0109:int 20


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


能编个毛线衣吗?
2016-06-10 14:20
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 5楼 wmf2014
不错,cd 20是古早dos的

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

2016-06-10 14:32
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
先谢谢wmf2014班竹也来玩儿

继续我们的缩小旅程…
回圈比标准写法复杂,似乎没有再缩小的空间,此路已走到尽头。
程式的迷宫中得找另一条捷径,我们想到资料表。

先建立一个三个资料的表格,每一项资料表示:字节,长度
就这样 buff db '0',10,'a',26,'A',26
改写程式

程序代码:
CODE segment
assume  cs:CODE,ds:CODE,es:CODE,ss:CODE
  org 100h
start:

 mov si,offset buff

 mov cx,3
S10:

 push cx

 lodsw ;读入DS:SI一个word入AX,并且SI自动加1,al=字节,ah=回圈长度
 mov cl,ah ;取回圈长度,这里ch已经=0
S20:

 mov ah,0eh

 int 10h

 inc al

 loop S20 ;内回圈
 pop cx  ;外回圈三次
 loop S10

 int 20h
buff db '0',10,'a',26,'A',26

CODE ENDS
END START


共29bytes,可以进一步缩小差距吗?
可以的,这里要借助dos的特性
特性一:
返回dos方式标准
 mov ah,4ch
 int 21h
早期的方式(不推荐)
 int 20h

另有更简单的方法:RET
程式被载内存,dos会为它保留100H作系统和程式沟通之用,
这叫PSP,PSP:0的偏移首2个BYTE是CD 20,CD 20便是INT 20H
只要CS指向PSP段,JMP 0就会跳到这道指令
而COM被载入时CS,DS,SS,ES都指向PSP段,SP指向FFFEH,栈顶处通常会是0
一通RET就弹出0值送入IP,然后跳去PSP:0,执行INT 20H

特性二:
列印字符方法有好几种,常用的
 mov dl,字符
 mov ah,2
 int 21h  ;----6 bytes

 mov al,字符
 mov ah,0eh
 int 10h  ;----也是6 bytes,但直接用al,不须经dl,在回路中应该可以减省空间
 
 其实dos另有一道后门,int 29h...快速输出字符
 mov al,字符
 int 29h

ok,把上面的程式换用这两个特性

程序代码:
CODE segment
assume  cs:CODE,ds:CODE,es:CODE,ss:CODE
  org 100h
start:

 mov si,offset buff

 mov cx,3
S10:

 push cx

 lodsw ;读入DS:SI一个word入AX,并且SI自动加1,al=字节,ah=回圈长度
 mov cl,ah ;取回圈长度,这里ch已经=0
S20:

 int 29h

 inc al

 loop S20 ;内回圈
 pop cx  ;外回圈三次
 loop S10

 ret

buff db '0',10,'a',26,'A',26

CODE ENDS
END START


26 bytes,很接近了!

顺便说说,有了dos这两个特性,题目一的7个bytes就不是什么难事了

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

2016-06-10 14:39
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
回复 7楼 Valenciax
学习了。
那是不是还要利用加载com文件寄存器自动清零不给al赋初值的特性?不然我还是做不到7byte。
0100:int 29
0102:inc al
0104:jnz 100
0106:ret

能编个毛线衣吗?
2016-06-10 15:07
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 8楼 wmf2014
对啊,根据经验,dos载入com/exe程式时,会把AX,BX和SI清0,但为了慎重起见,我特别写了一个程式,在刚进入程式时,记下并印出所有暂存器的值,分别在不同的dos版本测试,大致上是上面的观察结果
第1列是dosbox的结果
第2列是winxp下dos的结果
第3列是win7/32bit下dos的结果
都是AX,BX和SI清0,还有ch的值也都清0

图片附件: 游客没有浏览图片的权限,请 登录注册
2016-06-10 16:27
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
上面的显示只是仿debug的做法,这是大家习惯了的观看暂存器方式,实际上dos载入程式和debug是有分别的,dos载入大概是上面的样子,我们会发现ES指向psp段(其实ds也是指向psp,不过为了指向资料段被我改变了)
因为我是这样写的
Push ax
Mov ax,data
Mov ds,ax ;ds原值被改变了
Pop ax
Call prnitREG ;印出暂存器值



Debug载入程式则不同,除了sp,一般暂存器都清0,所以有些程式若未做暂存器初始化,在debug和dos下运行,会有不同的结果



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

2016-06-10 16:50
快速回复:大家来写写汇编小玩意
数据加载中...
 
   



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

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