回复 2楼 wmf2014
汇编果然千变万化,班竹的想法是另辟蹊径,也挺巧妙,利用栈操作,看来反倒不像我的一板一眼。
新的42bytes方案由54bytes那个优化的,就直接说说42bytes吧。
这里用最传统的int21h,0Ah函数读入字符串,取了长度后,直接在输入字符串前后补上空白。利用lodsb读入al,其中比较a-z用了这个方法
sub al,'a'
;减去ascii, a ->0 .... z ->25
cmp al,25 ;比较是否小写a-z内
若读入'a',减去'a',则字符'a'-'z'会转为值0-25,那么比较一次25就限制在a-z内,不用再2次比较。
mov eax,[si-2] ;取输入区4字节
这里利用32bit代码,直接取该字符前一位置之后4字节入EAX
再由输出区
1)
mov ebx,[di]取输出区4字节
若这EBX为空白,则该输出区为空白,直接放入EAX值,另把第4字节置空白
若EBX不为空白,比较cmp ah,bh,这是比较 [小写] 谁大,
若ah大,则新值置入该[输出区],交换EAX和EBX,新的EAX就是原来较小的值
增加输出区地址add di,4,再跳到1)从新和下值比较,如此就相当于泡泡法排序。
编写下来是42行,代码为了压缩空间,用的是比较新式的.MODEL TINY格式,
须用masm 6.x编译,直接转为
ML /AT ex2.asm
程序代码:
.MODEL TINY
.386
.code
ORG 100H
start: mov dx,offset inputBuf
mov ax,0c0ah ;清除键盘缓冲,并输入函数
int 21h
mov si,offset inputbuf + 2
xor ecx,ecx
mov cl,[si-1] ;取输入数
jcxz quit ;没输入,离开
mov byte ptr [esi+ecx],20h ;0d->20h 加空白于后
mov byte ptr [si-1],20h ;size->20h ;加空白于前
next: mov di,offset headbuf + 2
lodsb ;取字符
sub al,'a' ;减去ascii, a ->0 .... z ->25
cmp al,25 ;比较是否小写a-z内
ja next9 ;不是
mov eax,[si-2] ;取输入区4字节
next1: mov ebx,[di] ;取输出区4字节
cmp ebx,20202020h ;是否空白
jnz next2 ;不是
stosd ;空白则送到输出区
mov byte ptr [di-1],20h ;遮罩第4字节成空白
jmp short next9 ;回圈
next2: cmp ah,bh ;比较 [该小写] 谁大
ja next4 ;大于
next3: add di,4 ;少于则下一个
jmp short next1
next4: stosd ;取代输出区项目
mov byte ptr [di-1],20h ;遮罩第4字节空白
xchg ebx,eax ;交换二值,eax=原来输出区资料
jmp short next1 ;再和下一资料比较,即泡泡排序法
next9: loop next ;回圈 ; 因lodsb 已自动 inc si ;下一输入字节
mov dx,offset headbuf ;----印结果----
mov ah,9
int 21h
quit: mov ah,4ch ;离开
int 21h
headbuf db 0dh,0ah, 4 * 20 dup (20h),'$'
inputBuf db 21,0,21 dup(0)
end start ;-----------代码结束---------------
[此贴子已经被作者于2016-6-22 09:38编辑过]