Здравствуйте. По идее прога должна выводить в консоль 10 раз знак "!", а затем завершить свою работу. В ecx помещаю желаемое кол-во итераций, но "!" выводится всего 1 раз Посмотрел в pdf-ке про loop там тоже "что-то" (англ. знаю плохо =) про ecx... Да и в ДОСе вроде бы в cx... З.Ы. если поместить push ...&call [GetStdHandle] в тело цикла, то "!" выводиться почему-то 8 раз :/ З.З.Ы А если в olly смотреть, то цикл выполняется 8 раз всегда, независимо от ecx... бр-р-р... нич-ч-чего не понятно мне :/ ;------------------------------------------------ format PE console include '\include\win32a.inc' entry start section '.data' data readable writeable msg db "!", 13, 10, 0 section '.code' code readable executable start: push STD_OUTPUT_HANDLE call [GetStdHandle] mov ecx, 3 lbl1: push 1 push msg push eax call [WriteConsole] loop lbl1 push 0 call [ExitProcess] section '.import' import data readable library kernel32, 'kernel32' include '\include\apia\kernel32.inc' ;------------------------------------------------
Вызов WriteConsole может портить ecx, поэтоиу его лучше сохранять в стеке, а потом извлекать. Стоит также проверить, не портится ли eax.
Вот в таком виде работает. Пришлось запушить 2 нуля в стэк. (\include\pcount\kernel32.inc )Надо, наверное, в MSDN про WriteConsole посмотреть. [add] А вообще стоило мне на форуме поискать - WASM Phorum —› WASM.WIN32 —› Организация циклов при вызове API [/add] ;------------------------------------------------ format PE console include '\include\win32a.inc' entry start section '.data' data readable writeable msg db "!", 13, 10, 0 section '.code' code readable executable start: push STD_OUTPUT_HANDLE call [GetStdHandle] mov ecx, 3 lbl1: push ecx push eax push 0 push 0 push 3 push msg push eax call [WriteConsole] pop eax pop ecx loop lbl1 push 0 call [ExitProcess] section '.import' import data readable library kernel32, 'kernel32' include '\include\apia\kernel32.inc' ;------------------------------------------------
Для счетчика и хэндла консоли лучше использовать регистры ebx, esi, edi, т.к. они не изменяются api-функциями. Соответственно, нет необходимости на каждом проходе цикла сохранять их и снова считывать. ebx, esi, edi тоже нужно сохранять, но это делается один раз перед началом цикла. Code (Text): pushad push STD_OUTPUT_HANDLE call [GetStdHandle] mov ebx,eax mov esi,10 lbl1: push 0 push 0 push 3 push msg push ebx call [WriteConsole] dec esi jnz lbl1 popad push 0 call [ExitProcess] Компиляторы в качестве счётчика не используют ecx, если есть вызовы апи в цикле.
LOL ИМХО лучше вообще забыть о существовании инструкции LOOP Выигрыш в размере кода - один "несчастный" байт по сравнению с dec+jnz, а потери в скорости могут быть в разы. На всех современных процессорах LOOP - сложная инструкция (микропрограмма), состоящая не менее чем из 8-9 микроопераций. Соответственно, декодируется она не менее 3-х тактов (как 9 простых инструкций) и исполняется не менее 8-и. А парочка dec+jnz может декодироваться за один такт и выполняется за 2 PS: для оформления кода в сообщении используй тег Code (Text): - места меньше занимает, читать удобнее, да и по Правилам положено ;)
Спасибо =) Я этот LOOP в ДОСе юзал, когда немного под ним кодил =) А про Code (Text): я как-то забыл :/
leo Выйгрыш от loop ещё в том, что перед входом в цикл можно использовать jecxz, т.е. общий выйгрыш = 3 байта, если нет уверенности, что счётчик всегда инициализируется != 0.
Так... я не понял, стоит ли его использовать и если "да", то при каких условиях. Я, конечно, понимаю, что либо "код меньше", либо "код быстрее работает". Не всегда конечно...