Немного странно, что вы передаете в функцию две длины. Все виды плохих вещей могут произойти, если два несовпадения.
Лучше передать длину строки в явном виде или сделать так, чтобы код вычислил длину.
Поскольку получение длины старой c-строки в skool нетривиально для кода, но тривиально для Google, я просто передам ее в качестве параметра.
'... неверный вывод.'
Проблема в том, что ваши строки должны заканчиваться нулем, но вы не ставите конечный ноль в строке назначения.
Прежде всего, если вы хотите, чтобы строка была допустимой строкой в стиле c, убедитесь, что вы добавили завершающий ноль, например так: source db "test test",0
mov esi, OFFSET source ;Start of source
mov edi, OFFSET target ;start of dest
;length EQU SIZEOF source ;we are reversing source
mov ecx, SIZEOF source ;Length of the string
;(includes the terminating 0)
Setup:
;//a c-string must have a terminating 0!
xor eax,eax ;al=0, put the terminating zero in first
L1:
mov [edi+ecx-1], al ;if length(ecx)=1, then write to [edi] directly.
mov al, [esi]
inc esi
loop L1
Замечания по коду
Нет необходимости держать в полете три счетчика (edi
, esi
, ecx
), достаточно двух. esi
обратный отсчет, ecx
обратный отсчет.
В x86 есть много действительно полезных режимов адресации, которые в основном бесплатны.
Последняя итерация будет читать конечный ноль в al
, нам не нужно менять это на обратное, и вы уже написали его в начале, поэтому он (молча) отбрасывается.
Из-за завершающего нуля длина равна по крайней мере 1. Это хорошо, потому что если вы каким-то образом будете вводить 0 в loop
, это будет цикл 'навсегда'; не хорошо («навсегда» 4 миллиарда раз) .
Обратите внимание, что ваш код не учитывает Unicode, поэтому он не будет работать для UTF8, но давайте предположим, что это всего лишь учебное упражнение.
Если вы следуете ABI , то вы можете просто передать параметры в регистрах, то есть вы можете пропустить некоторые инициализации. Учитывая, что ваш код не получит никаких призов за скорость, я пропустил этот шаг.