我很好奇这是否以前做过,不一定是否具有实用价值(尽管空间效率的提高是显而易见的)。是否曾经在同一机器代码中编码多个指令?例如:
(这完全是编造的)
0xAEA2 -> 添加 R3 0xA2
0xEAE6 -> 移动 R1 0xE6
0xAAAA ...
通过向左移动一个半字节来重新解释机器代码变成:
0xEA2E -> 移动 R1 0x2E
0xAE5A -> 添加 R3 0x5A
我很好奇这是否以前做过,不一定是否具有实用价值(尽管空间效率的提高是显而易见的)。是否曾经在同一机器代码中编码多个指令?例如:
(这完全是编造的)
0xAEA2 -> 添加 R3 0xA2
0xEAE6 -> 移动 R1 0xE6
0xAAAA ...
通过向左移动一个半字节来重新解释机器代码变成:
0xEA2E -> 移动 R1 0x2E
0xAE5A -> 添加 R3 0x5A
在 Smalltalk 78(所有现代 Smalltalk 方言的前身之一)的实现中,有一个双字节存储参数 0字节码,其第二个字节是加载参数 0。以这种方式,跳转到存储指令开头的代码执行存储,而跳转到它的中间(!)导致加载。您可以在Reviving Smalltalk-78 - Bert Freudenberg - IWST 2014 - 大约30 分钟-中了解更多信息
这并不新鲜。几年前,我们曾经举办过小型代码优化比赛。例如,下面的代码仅用 42 个字节实现了 C 函数strcpy
、、strncpy
和stpcpy
。我在 1993 年写了这个。16 位 8086 汇编语言,C 可调用,在堆栈上传递参数,调用者清理堆栈。
请注意,入口点strcpy
只是指令的第一个字节,它将接下来的两个字节加载到 AX 寄存器中。而db 3Ch
是另一条指令的第一个字节,它消耗下一个字节(or al
),然后执行由 执行的STC
指令的第二个字节的or al,0F9h
指令strncpy
。
创建一个列表文件以获取操作码,然后跟踪三个入口点中的每一个点发生的情况是很有指导意义的。
当我们修补现有代码时,这些技巧会派上用场。有时我们可以在不更改任何关键部分的地址的情况下为 .COM 文件制作二进制补丁。当我们有必须是 16 字节(或更大)对齐的东西时,这一点很重要,而且我们不想浪费 15 字节的死空间,只是为了添加另一条指令。哦,当你只有 64 K 字节可用时你会玩的游戏。
Ideal
Model Small,c
CodeSeg
Public strcpy,strncpy,stpcpy
;
; 42 bytes
;
; char * strcpy (char *dest, char *src);
;
strcpy:
db 0B8h ;mov ax,immed
;
; char * stpcpy (char *dest, char *src);
;
stpcpy:
mov al,0Ch ;0Ch is the opcode for OR AL,immediate
mov cx,0ffffh ;make max count
db 3Ch ;cmp al,immediate
;stpcpy - CF set, ZF set
;strcpy - CF set, ZF clear
;
; char * strncpy (char *dest, char *src, unsigned len);
;
strncpy:
or al,0F9h ;strncpy - CF clear, ZF clear
;0F9h is the opcode for STC,
;which is executed by strcpy and stpcpy
pop dx ;return address in DX
pop bx ;dest string in BX
pop ax ;source string in AX
jc l0 ;if strncpy
pop cx ;then get length in CX
push cx ;and fixup stack
l0:
push ax ;more stack fixup
push bx ;save return value
push si ;gotta save SI
xchg si,ax ;SI points to source string
lahf ;save flags for exit processing
l1:
lodsb ;get character
l2:
jcxz Done ;done if count = 0
mov [bx],al ;store character
inc bx ;bump dest
or al,al ;if character is 0 or
loopnz l1 ;if at end of count, then done
sahf ;restore flags
ja l2 ;for strncpy(), must loop until count reached
Done:
pop si ;restore SI
pop ax ;return value in AX
jnz AllDone ;done if not stpcpy
xchg ax,bx ;otherwise return pointer to
dec ax ;end of string
AllDone:
call dx ;return to caller
End
我记得我花了几个小时想出那个只是为了打败我的一个朋友,他总是在这些比赛中击败我。他花了几分钟查看它并从中刮出另一个字节。
Redcode 初学者指南,1.22 版,版权所有 1997-2004 Ilmari Karonen:
...
Core War(或Core Wars)是一种编程游戏,其中汇编程序试图在模拟计算机的内存中相互摧毁。这些程序(或勇士)是用一种叫做Redcode的特殊语言编写的,并由一个叫做MARS(Memory Array Redcode Simulator)的程序运行......
这个游戏的乐趣在于通过类似于你的“移动nibbles”的操作修改机器代码后重新解释机器代码。
有关更多信息,请参见http://www.corewars.org/information.html ...