8086机器代码+ DOS,61字节
十六进制转储(右侧为ASCII视图):
B8 1E 01 8B F8 CD 21 B1 1F F2 AE 8B F7 AC 8A D0 ......!.........
B4 02 CD 21 80 E2 20 74 02 CD 21 E2 F0 C3 71 77 ...!.. t..!...qw
65 72 74 79 75 69 6F 70 0D 0A 61 73 64 66 67 68 ertyuiop..asdfgh
6A 6B 6C 0D 0A 7A 78 63 76 62 6E 6D 0D jkl..zxcvbnm.
汇编源代码(可以用tasm汇编):
.MODEL TINY
.CODE
org 100h
MAIN PROC
mov ax, offset qwerty ; sets ah=1 (coincidence)
mov di, ax ; di points to the string
int 21h ; reads a char from keyboard into al
mov cl, 31 ; cx is the length of the string
repne scasb ; look for the char
mov si, di ; si now points beyond the found char
myloop:
lodsb ; load a char
mov dl, al
mov ah, 2
int 21h ; output the char
and dl, 20h ; if it's a letter, set it to a space
jz print_done ; if it's not a letter, don't print a space
int 21h ; if it's a letter, print a space
print_done:
loop myloop ; repeat until end of string
ret
qwerty db 'qwertyuiop',13,10,'asdfghjkl',13,10,'zxcvbnm',13
MAIN ENDP
END MAIN
这里有两个有趣的事情:
qwerty
字符串的偏移量是0x011e
。它的高字节是1,它是字符输入的DOS功能号。这将在代码中节省1个字节。
- 所有小写字母都设置了位5。当这样做的
AND
用0x20
,它们都被转变成的空间中,然后将其打印出来。如果前一个字符是行尾字节,则将其变为0,并且不输出任何空格。这用于避免0d 20 0a 20
行尾出现不必要的序列。
一件事几乎很有趣:
我尝试搜索从地址0(将程序大小减少2个字节)开始的输入char,而不是通常的位置(字符串的开头)。这几乎起作用了;但是,输入失败t
,因为代码本身包含字节t
(作为条件跳转的编码的一部分)。因此,对于t
,它将输出一些垃圾字节: