x86机器码,70个字节
60 89 d7 31 db 43 88 ce b2 fe 49 d1 e1 87 da 0f
c7 f0 24 7f 3c 22 72 f7 48 3c 79 74 f2 3c 59 74
ee aa 49 7c 1c 00 df 79 06 86 f7 42 43 eb f6 f6
c3 01 74 03 b0 0a aa 51 88 f9 b0 20 f3 aa 59 eb
cc c6 07 00 61 c3
我的可执行代码,反汇编为:
0000003d <myheh>:
3d: 60 pusha
3e: 89 d7 mov %edx,%edi
40: 31 db xor %ebx,%ebx
42: 43 inc %ebx
43: 88 ce mov %cl,%dh
45: b2 fe mov $0xfe,%dl
47: 49 dec %ecx
48: d1 e1 shl %ecx
0000004a <myloop>:
4a: 87 da xchg %ebx,%edx
0000004c <myrand>:
4c: 0f c7 f0 rdrand %eax
4f: 24 7f and $0x7f,%al
51: 3c 22 cmp $0x22,%al
53: 72 f7 jb 4c <myrand>
55: 48 dec %eax
56: 3c 79 cmp $0x79,%al
58: 74 f2 je 4c <myrand>
5a: 3c 59 cmp $0x59,%al
5c: 74 ee je 4c <myrand>
5e: aa stos %al,%es:(%edi)
5f: 49 dec %ecx
60: 7c 1c jl 7e <mydone>
00000062 <mylab>:
62: 00 df add %bl,%bh
64: 79 06 jns 6c <myprint>
66: 86 f7 xchg %dh,%bh
68: 42 inc %edx
69: 43 inc %ebx
6a: eb f6 jmp 62 <mylab>
0000006c <myprint>:
6c: f6 c3 01 test $0x1,%bl
6f: 74 03 je 74 <myprint1>
71: b0 0a mov $0xa,%al
73: aa stos %al,%es:(%edi)
00000074 <myprint1>:
74: 51 push %ecx
75: 88 f9 mov %bh,%cl
77: b0 20 mov $0x20,%al
79: f3 aa rep stos %al,%es:(%edi)
7b: 59 pop %ecx
7c: eb cc jmp 4a <myloop>
0000007e <mydone>:
7e: c6 07 00 movb $0x0,(%edi)
81: 61 popa
82: c3 ret
该函数在ecx中接收X的大小,并在edx中接收指向输出缓冲区的指针。
它按字节顺序填充输出缓冲区。有2 * n - 1
迭代(等于要输出的非空格字符的数量)。在每次迭代中,它执行以下操作:
- 产生一个随机数
- 轻敲数字以使其适合范围;如果不好,请返回并重新生成
- 打印随机字符
- 打印换行符(每隔一个迭代)
- 打印适当数量的空格
从随机数到随机字符的转换并不明显:
myrand:
rdrand eax;
and al, 7fh;
cmp al, 22h;
jb myrand;
dec eax;
cmp al, 'y';
je myrand;
cmp al, 'Y';
je myrand;
有趣的部分是空间数量的计算。它必须生成以下数字(例如,N = 9):
7 1
5 2
3 3
1 4
3
1 2
3 1
5 0
7
这些数字是从两个算术级数中交替获取的。第一个在步骤-2处下降,第二个在步骤1处上升。当第一个级数到达-1(在X的中间)时,出现毛刺(已除去-1),然后进度会改变方向。
的级数被存储在寄存器ebx
和edx
-高部分bh
和dh
存储当前数量,以及低的部分bl
和dl
存储的步骤。为了在级数之间交替,代码用交换了寄存器xchg
。
当级数达到-1(在mylab
标签附近)时,它将增加两个寄存器,将步骤从切换-2, 1
到-1, 2
。这也改变了寄存器的作用,因此它交换了寄存器的高位。
在函数的末尾,它存储一个零字节以指示字符串的结尾。