Да, хитро' написано
Можно попробовать 135 байт сэкономить, храня слова по 5 бит на букву - это 4 символа в 20 битах (т.е. не кратно байту) вместо теперешних 32. А можно ещё и статистически подойти к вопросу поглядев на распределение вероятностей:
Code: Select all
0) . [32] = 88
1) A [65] = 21
2) B [66] = 5
3) C [67] = 29
4) D [68] = 18
5) E [69] = 6
6) G [71] = 1
7) H [72] = 12
8) I [73] = 19
9) J [74] = 11
10) K [75] = 2
11) L [76] = 21
12) M [77] = 11
13) N [78] = 13
14) O [79] = 9
15) P [80] = 18
16) R [82] = 26
17) S [83] = 16
18) T [84] = 9
19) U [85] = 5
20) V [86] = 3
21) X [88] = 11
22) Z [90] = 6
Как можно видеть реально используются только 22 латинские буквы вместо 26 (плюс пробел) - если тупо математически, то это 22^4=234256, что умещается в 18 битах - уже экономия 157 байт (хотя тот факт, что оно не кратно байту добавит лишнего кода), а если ещё и отсортировать по частоте:
Code: Select all
0) . [32] = 88
3) C [67] = 29
16) R [82] = 26
1) A [65] = 21
11) L [76] = 21
8) I [73] = 19
4) D [68] = 18
15) P [80] = 18
17) S [83] = 16
13) N [78] = 13
7) H [72] = 12
9) J [74] = 11
21) X [88] = 11
12) M [77] = 11
18) T [84] = 9
14) O [79] = 9
5) E [69] = 6
22) Z [90] = 6
2) B [66] = 5
19) U [85] = 5
20) V [86] = 3
10) K [75] = 2
6) G [71] = 1
то можно типа какого-то микрохаффмана организовать пользуясь этой информацией:
Code: Select all
Space,10
C,1110
R,1101
L,0101
A,0100
I,0011
P,0001
D,0000
S,11111
N,11001
H,11000
M,01110
X,01101
J,01100
O,00100
T,111101
Z,111100
E,011111
U,001011
B,001010
V,0111101
K,01111001
G,01111000
что даст:
Code: Select all
MOV -> 19 bits
MVI -> 18 bits
STAX -> 20 bits
LDAX -> 17 bits
STA -> 17 bits
LDA -> 14 bits
LXI -> 15 bits
SHLD -> 18 bits
LHLD -> 17 bits
PUSH -> 20 bits
POP -> 15 bits
SPHL -> 18 bits
XCHG -> 22 bits
XTHL -> 20 bits
IN -> 11 bits
OUT -> 19 bits
CMC -> 15 bits
STC -> 17 bits
CMA -> 15 bits
DAA -> 14 bits
INR -> 15 bits
DCR -> 14 bits
INX -> 16 bits
DCX -> 15 bits
ADD -> 14 bits
ADC -> 14 bits
SUB -> 19 bits
SBB -> 19 bits
ANA -> 15 bits
ORA -> 15 bits
XRA -> 15 bits
CMP -> 15 bits
ADI -> 14 bits
ACI -> 14 bits
SUI -> 17 bits
SBI -> 17 bits
ANI -> 15 bits
ORI -> 15 bits
XRI -> 15 bits
CPI -> 14 bits
DAD -> 14 bits
RLC -> 14 bits
RAL -> 14 bits
RRC -> 14 bits
RAR -> 14 bits
PCHL -> 17 bits
JMP -> 16 bits
CALL -> 16 bits
RST -> 17 bits
RET -> 18 bits
JNZ -> 18 bits
JZ -> 13 bits
JNC -> 16 bits
JC -> 11 bits
JPO -> 16 bits
JPE -> 17 bits
JP -> 11 bits
JM -> 12 bits
CNZ -> 17 bits
CZ -> 12 bits
CNC -> 15 bits
CC -> 10 bits
CPO -> 15 bits
CPE -> 16 bits
CP -> 10 bits
CM -> 11 bits
RNZ -> 17 bits
RZ -> 12 bits
RNC -> 15 bits
RC -> 10 bits
RPO -> 15 bits
RPE -> 16 bits
RP -> 10 bits
RM -> 11 bits
EI -> 12 bits
DI -> 10 bits
HLT -> 17 bits
NOP -> 16 bits
DSUB -> 21 bits
ARHL -> 17 bits
RLDE -> 18 bits
RIM -> 15 bits
SIM -> 16 bits
LDHI -> 17 bits
LDSI -> 17 bits
RSTV -> 22 bits
SHLX -> 19 bits
LHLX -> 18 bits
JNK -> 20 bits
JK -> 15 bits
однако из-за того, что нам надо одинаковое смещение между словами, то придётся брать максимум из получившегося, а это 22 бита - округляем до 24, что есть 3 байта на слово или 270 байт на весь словарь, что даёт выгоду только в 90 байт по сравнению с первоначальным вариантом. Можно комбинированный вариант сделать - быстро получаем доступ к коротким словам и чуть более долгий для длинных - скажем 20 бит и меньше храним вместе и 21-22 - храним отдельно. Выходит, что отдельно идут только:
Code: Select all
XCHG -> 22 bits
DSUB -> 21 bits
RSTV -> 22 bits
и этот вариант всё равно получается хуже, чем первый, значит нафиг микрохаффмана - проще всего пойти по 5-битному пути на букву (первый вариант).
Однако если наплевать на быстродействие и просто расположить все мнемоники битовой цепочкой, то с использованием микрохаффмана они займут всего 179 байт т.е. экономя 181 байт - почти в 2 раза меньше! Однако ещё надо прикинуть сколько будет весить код, раскодирующий эти мнемоники деревом...
P.S. Можно двух и трёх-буквенные мнемоники сделать "быстрыми", а четырёхбуквенные (18 штук) - медленными:
Code: Select all
ARHL
CALL
DSUB
LDAX
LDHI
LDSI
LHLD
LHLX
PCHL
PUSH
RLDE
RSTV
SHLD
SHLX
SPHL
STAX
XCHG
XTHL
в таком случае таблица быстрых мнемоник будет храниться в 3*5=15 битах на слово и 16-й бит будет означать, что нужно откуда-то вычитать четвёртую букву, т.е. это будет 90*2=180 байт плюс логика "дописывания" четвёртой буквы (надо прикинуть сколько байт она может занять и стоит ли оно вообще того). Четвёртых букв у нас только 9:
Code: Select all
5 L
4 X
2 I
2 D
1 V
1 H
1 G
1 E
1 B
и ещё у 8085-х инструкций надо пометочку поставить, что они не родные...
P.P.S. Сложноватая логика потребуется, чтобы четвёртую букву программно дописывать:
Code: Select all
STAX 02,12
LDAX 0A,1A
SHLD 22
LHLD 2A
PUSH C5,D5,E5,F5
SPHL F9
XCHG EB
XTHL E3
PCHL E9
CALL CD
DSUB 08 *
ARHL 10 *
RLDE 18 *
LDHI 28 *
LDSI 38 *
RSTV CB *
SHLX D9 *
LHLX ED *
4th letter:
L -> F9,E3,E9,CD,10
X -> 02,12,0A,1A,D9,ED
I -> 28,38
D -> 22,2A
V -> CB
H -> C5,D5,E5,F5
G -> EB
E -> 18
B -> 08
я там звёздочки поставил у четырёхбуквенных инструкций от 8085, а вот остальные:
Code: Select all
RIM 20 *
SIM 30 *
JNK DD *
JK FD *