Если только невозможно иначе, то вы не должны использовать инструкции, которые оперируют словами, более правильно использовать те, которые работают с переменными типа двойное слово. Байтовый доступ еще может иногда использоваться, но остерегайтесь использовать операции со словами. Ниже пример использования 32-битного алгоритма для поиска символа в строке. Идея основана на генерации уникального значения, если и только если символ найден. Поскольку пример обрабатывает строку по четыре байта за раз, то это значительно быстрее, чем обработка по одному байту за раз, несмотря на дополнительное усложнение, поскольку требуется обрабатывать сразу четыре байта.
function ScanStrForChar(C: Char; S: String): Integer; register;
asm
push EBX
push EDI
push ESI
test EDX,EDX
jz @notfound
mov ESI,[EDX-4]
test ESI,ESI
jz @notfound
add ESI,EDX
mov ah,al
mov di,ax
shl EDI,16
or di,ax
mov EAX,EDX
lea EDX,[EAX+3]
@L1:
cmp EAX,ESI
ja @notfound
mov EBX,[EAX]
xor EBX,EDI
add EAX,4
lea ECX,[EBX-$01010101]
not EBX
and ECX,EBX
and ECX,$80808080
jz @L1
mov EBX,ECX
shr EBX,16
test ECX,$8080
jnz @L2
mov ECX,EBX
@L2:
lea EBX,[EAX+2]
jnz @L3
mov EAX,EBX
@L3:
shl cl,1
sbb EAX,EDX
inc EAX
@ending:
pop ESI
pop EDI
pop EBX
ret
@notfound:
xor EAX,EAX
jmp @ending
end;
В зависимости от длины обрабатываемых строк, функция может быть быстрее стандартной функции pos раза в два. Заметим, что должна прочитать от одного до трех символов в конце строки, но в текущей версии компилятор всегда размещает строки по модулю четыре, так что, это не приносит проблем, но нельзя гарантировать, что в следующих версиях это будет так же. Вы можете устранить эту проблему, путем расчета остатка символов в конце строки по модулю четыре и обработать остаток побайтно. Вы потеряете некоторое быстродействие, но выиграете в надежности. Заметим, что компилятор добавляет одну или несколько инструкций ret после jmp @ending. Но они никогда не будут выполнены, поскольку мы включили инструкцию ret сами.
Вы должны избегать подобных вещей, поскольку если нужен фрейм стека, то вы должны будете сами написать код выхода (см. главу 1.2, где рассмотрены коды входа и выхода). В вышеприведенном примере нет фрейма стека, так что нет нужды и в коде выхода. Вы можете избежать этой проблемы, путем добавления инструкции jmp для условия, когда символ не найден, это просто пропустит установку результата в ноль, если строка пустая или символ не найден. После этого пример будет выглядеть так:
...
shl cl,1
sbb EAX,EDX
inc EAX
jmp @ending
@notfound:
xor EAX,EAX
@ending:
pop ESI
pop EDI
pop EBX
end;
Но, в этом случае вы будете вынуждены всегда добавлять дополнительную инструкцию jmp в ваш алгоритм, который немного от этого замедлится. Если вы обрабатывает достаточно длинные строки, то это почти незаметно на общем процессе обработке, и добавленный код может быть субъектом для оптимизации в дальнейшем, когда это станет важным.