Оптимизация для процессоров семейства Pentium: 23. Уменьшение размера кода (все процессоры) — Архив WASM.RU
Как было объяснено в главе 7, размер кода кэша равен 8 или 16 килобайтам. Если у вас есть подозрение, что критические части кода не поместятся в кэш, тогда вы можете подумать о том, чтобы уменьшить их размер.
32-х битный код обычно больше, чем 16 битный код, потому что адреса и константы занимают 4 байта в 32-х битном режиме, а 16-ти битном режиме только два. Тем не менее, 16-ти битный код другие потери, такие как префиксы и проблемы с соседнеми словами памяти (смотри главу 10.2). Некоторые другие методы для уменьшения размера кода обсуждаются ниже.
Оба адреса перехода, адреса данных и константы занимают меньше места, если их значение находится между -128 до +127.
Для адресов переходов это означает, что короткие переходы занимают два байта, в то время как переходы более чем 127 байт занимают 5 байтов, если переход безусловный и 6 байтов, если условный.
Таким же образом адреса данных занимают меньше места, если они могут быть выраженны как указатель в интервале от -128 до +127
Пример:
Код (Text):
MOV EBX,DS:[100000] / ADD EBX,DS:[100004] ; 12 байтУменьшаем размер:
Код (Text):
MOV EAX,100000 / MOV EBX,[EAX] / ADD EBX,[EAX+4] ; 10 байтПреимущество использования указателя становится еще более очевидным, если вы используете его много раз. Хранение данных в стеке и использование EBP или ESP в качестве указателя сделает ваш код меньше, чем если бы вы использовали абсолютные адреса, если только, конечно, ваши данные в пределах +/-127 байтах указателя. Использование PUSH и POP для записи и чтения временных данных еще короче.
Константы могут также занимать меньше места, если они между -128 и +127. Большинство инструкций с числовыми операндами имеют короткую форму, где операнд - это один байт со знаком.
Примеры:
Код (Text):
PUSH 200 ; 5 байт PUSH 100 ; 2 байт ADD EBX,128 ; 6 байт SUB EBX,-128 ; 3 байтСамая важная инструкция с числовым операндом, у которой нет короткой формы, это MOV.
Примеры:
Код (Text):
MOV EAX, 0 ; 5 байтМожно заменить на:
Код (Text):
XOR EAX,EAX ; 2 байтаИ
Код (Text):
MOV EAX, 1 ; 5 байтовМожно заменить на:
Код (Text):
XOR EAX,EAX / INC EAX ; 3 байтаили:
Код (Text):
PUSH 1 / POP EAX ; 3 байтаИ
Код (Text):
MOV EAX, -1 ; 5 байтаМожно заменить на:
Код (Text):
OR EAX, -1 ; 3 байтаЕсли один и тот же адрес или константа используется несколько раз, вы можете загрузить ее в регистр. MOV с 4-х байтным числовым операндом иногда можно заменить на арфметическую инструкцию, если известно значение регистра до MOV.
Пример:
Код (Text):
MOV [mem1],200 ; 10 байтов MOV [mem2],200 ; 10 байтов MOV [mem3],201 ; 10 байтов MOV EAX,100 ; 5 байтов MOV EBX,150 ; 5 байтовПредполагая, что mem1 и mem3 находятся в пределах -128/127 байтов от em2, это можно изменить на:
Код (Text):
MOV EBX, OFFSET mem2 ; 5 байтов MOV EAX,200 ; 5 байтов MOV [EBX+mem1-mem2],EAX ; 3 байта MOV [EBX],EAX ; 2 байта INC EAX ; 1 байт MOV [EBX+mem3-mem2],EAX ; 3 байта SUB EAX,101 ; 3 байта LEA EBX,[EAX+50] ; 3 байтаОстерегайтесь задержек AGI в инструкции LEA (для PPlain и PMMX).
Также стоит учитывать то, что разные инструкции имеют разную длину. Следующие инструкции занимают только один байт и поэтому очень привлекательны: PUSH reg, POP reg, INC reg32, DEC reg32. INC и DEC с 8-ми битовыми регистрами занимают 2 байта, поэтому 'INC EAX' короче, чем 'INC AL'.
'XCHG EAX,reg' также однобайтовая инструкция и поэтому занимает меньше места, чем 'MOV EAX,reg', но это медленнее.
Некоторые инструкции занимают на один байт меньше, когда они используют аккумулятор, а не другой регистр.
Пример:
Код (Text):
MOV EAX,DS:[100000] меньше, чем MOV EBX,DS:[100000] ADD EAX,1000 меньше, чем ADD EBX,1000Инструкции с указателями занимают на один байт меньше, чем когда они используют адресацию по базе (не ESP) со сдвигом, а не косвенную адресацию с масштабированием, или и то, и другое вместе, или ESP в качестве базы.
Примеры:
Код (Text):
MOV EAX,[array][EBX] меньше, чем MOV EAX,[array][EBX*4] MOV EAX,[EBP+12] меньше, чем MOV EAX,[ESP+12]Инструкции с EBP в качестве базы без смещения занимают на один байто больше, чем при использовании других регистров:
Код (Text):
MOV EAX,[EBX] меньше чем MOV EAX,[EBP], но MOV EAX,[EBX+4] такого же размера, как и MOV EAX,[EBP+4]Также адресация со сдвигом бывает выгоднее, чем адресация с масштабированием:
© Агнер Фог, пер. AquilaКод (Text):
LEA EAX,[EBX+EBX] короче, чем LEA EAX,[2*EBX]
Оптимизация для процессоров семейства Pentium: 23. Уменьшение размера кода (все процессоры)
Дата публикации 22 авг 2002