23 способа получить в регистре единицу. От самых простых до самых извратных. Хорошая разминка для мозгов. 1. непохек Code: mov eax,1. Просто положить в регистр единицу 2. Code: sub eax,eax /xor eax,eax (по отдельности не рассматриваю) inc eax Красиво, довольно коротко. Обнуляем, инкрементируем.... 3. Code: imul eax,0 inc eax Тоже красиво. Обнуляем, инкрементируем 4. Сопроцессор, но тут нужна дополнительная переменная. mem dword ? Code: finit fld1 fist mem mov eax,mem в eax - теперь 1 Сначала мы инициализируем сопроцессор (finit), потом загружаем в st0 1, потом отправляем содержимое st0 в mem, mem ложим в eax ) 5. Еще сопроцессор ( mem dword ?) Code: finit fldpi fcos fchs fist mem mov eax,mem То есть ложим в st0 число пи, находим косинус пи (-1), меняем знак, сохраняем значение 6. А теперь больше тригонометрии Code: finit fldz fcos fist mem mov eax,mem Ищем косинус от нуля))))) А это 1))) 7. А еще можно так Code: sub eax,eax sub al,-1 это 4 байта. 8. Самый мой любимый способ Code: sub eax,eax bfs eax,0 В нулевой бит ложим 1=) 9. Code: lea eax,[1] Длинно, но все же.... 10. Разновидность 5 метода, но беру модуль Code: finit fldpi fcos fabs fist mem mov eax,mem 11. Code: sub eax,eax dec eax imul eax,eax Ну это всем наверное ясно -1*(-1)=1 12. Этот способ я тоже люблю. Делим двоичный логарифм 10 сам на себя.Аналогичный способ с любым др. числом (например с натуральным логарифмом 2 - оба способа рассматриваются) Code: finit fld2t fld2t fdiv st0,st1 fist mem mov eax,mem и соответственно Code: finit fldln2 fldln2 fdiv st0,st1 fist mem mov eax,mem а можно еще с числом пи и десятичным логарифмом 2 Code: finit fldpi fldpi fdiv st0,st1 fist mem mov eax,mem и Code: finit fldlg2 fldlg2 fdiv st0,st1 fist mem mov eax,mem 13. Тригонометрия. Что-то меня тригонометрия в последнее время вдохновляет. Вариация на тему основного тригонометрического тождества. Code: finit fldln2 ; натуральный логарифм 2 fcos ; получаем косинус fldln2 fcos fmul st,st(1) ; (cos(ln2))^2 fldln2 fsin ; теперь синус fldln2 fsin fmul st(1),st ; (sin(ln2))^2 fincstp fadd st,st(1) ; st0+st1=1 по основному тригонометрическому тождеству fist mem 14. Красивый способ Code: stc ; установка флага переноса в 1 sbb eax,eax ; вычитание с заемом neg eax ; -(-1)=1 15. В еax будет true, то есть 1 Code: sub eax,eax cmp eax,eax sete al 16. Еще извратный способ Code: sub eax,eax sub ecx,ecx dec eax mov cx,1fh m1: btc eax,ecx ; фишка в этой команде. инвертируем все биты, кроме последнего, тогда в самом регистре будет 1 loop m1 17.А еще можно так Code: sub eax,eax stc ; установка флага переноса в 1 adc eax,eax ; сложнение с учетом флага переноса CF 18.Простенько, но со вкусом Code: sub eax,eax or eax,1 19. Почти тоже самое Code: xor eax,eax xor eax,1 20.Обалденный способ. 4 bsr над -1 и получаем 1) Code: sub eax,eax dec eax bsr eax,eax bsr eax,eax bsr eax,eax bsr eax,eax 21. Тоже вариант Code: sub eax,eax dec eax shr eax,1fh ; логический сдвиг вправо 22. Скушный метод, но результат тот же Code: xor eax,eax dec eax and eax,1 23. Довольно неинтересно.. но все же Code: xor eax,eax dec eax neg eax Пока на этом все......
Это все конечно круто, только зачем мне куча каких-то извращенных способов, если обычно используются 3-4 способа из списка? Причем по размеру они выигравают все остальные. Честно говоря, похоже на детское хвастовство, теперь сделай 23 способа как получить -1 в регистре. Без обид, но лучше вкладывать свой потенциал во что-то более серьезное.
Ну цель вообще другая была... А именно Выйти за рамки стандартных команд так сказать. Я таким образом после дня напряженной учебы расслабляюсь думаю их больше... тоже мысль. ЗЫ Ясное дело, что лучше всего Code: sub eax,eax inc eax это всего 3 байта. Но юзают-то в основном mov eax,1 а это 5 байт=\\\\ Так что материал полезен для общего развития)
+7 до 30 тоже 3 байта (константа до 255 для W32) Code: push 1 pop eax с использованием API, которая обязательно возвратит 0 Code: invoke IsWindow,-1 inc eax ; неудобный метод Code: push 1 push esp pop esi lodsd pop esi способ с исчезновением стека Code: stc ;<- 1 pushfd xchg esi,esp lodsd xchg esi,esp and eax,1 мешает отладке Code: call @1 dd 1 @1: pop eax mov eax,[eax] всего 11 байт запутанное зануление EAX Code: movzx ebx,ax xchg ebx,eax bswap eax movzx ebx,ax xchg ebx,eax inc eax полное извращение, но прикольно Code: call @2 @2: pop esi push esi std lodsb sub [esp],esi cld pop eax
Так он понятнее. Понятность кода намного важнее размера и скорости ) Есть конечно пара исключений, но это редкость.
А я наоборот, полностью согласен с nerezus. Скорость, быстродействие - зависит от скила кодера в данный момент времени. А вот понятность кода, возможность его модернизации - это, так сказать, на все времена! Но это отнюдь не означает, что надо писать медленный и алгоритмически неправильный код в ушерб понятности. надо знать меру : ). По теме: асм не знаю, заметил лишь одно: не "ложим", а "кладем" - рус.яз. рулит : )
Клево. "Кладем"... Важное замечание такое))))))))) В чем смысл? Я уже писала в чем смысл.... в далеком октябре. Читаем пост номер 1 вторая строка второе предложение. Читаем пост номер три. ЦЕЛИКОМ. нууууууу))))))) ну ладно... пусть будет. 31-й.
Мой код эффективнее Code: .386 .model flat, stdcall ExitProcess PROTO ,:DWORD MessageBoxA PROTO ,:DWORD, :DWORD, :DWORD, :DWORD .data MsgBoxCaption db "Внимание",0 MsgBoxText db "Нажмите пожалуйста клавишу A(обязательно с шифтом, а то прога заглючит нах)",0 .const NULL equ 0 MB_OK equ 0 .code Main: INVOKE MessageBoxA, NULL, ADDR MsgBoxText, ADDR MsgBoxCaption, MB_OK h AX=0168 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0102 NV UP EI PL NZ NA PO NC 0ABD:0102 96 XCHG SI,AX - INVOKE ExitProcess, NULL end Main
Для этого есть "высокоуровневый ассемблер" - лучший язык в мире С. Ассемблер нужно использовать только там, где без него нельзя обойтись и можно использовать для оптимизации кода, ни о какой понятности кода речь не идет.
>> а зачем писать fdiv st0,st1 когда проще fdivp? а вы предлагайте новые способы, не стесняйтесь. Следуйте примеру Xserg) Здесь я и не думала писать, что проще. Просто рассмотрела пару десятков извратных способов. mov eax,1 - это было весьма скушно. Приятно, что тема не умерла и кому-то это еще интересно.
xor ecx,ecx jecxz m @m: inc ecx вот только что еще пришло в голову с loop ..... @m: loop m ..... суть в том,что если надо обнулить ecx,то как раз будет цикл пока в ecx не будет 0,после чего можно inc ecx по желанию
я теперь понял еще одно отличие кодера с античата (хэкера) от программиста: программист не будет искать еще один способ получить в регистре 1, и тем более через жопу, тогда как кодер с античата следуя манифесту хэкера задействует все самые бесполезные инструкции. что ж вы еще системные вызовы не подключили, по-моему супер это записать 1 на диск и считать ее же в регистр. 0x0c0de бездельник и тунеядец! эхх...
Еще боюсь,что можно shr,shl идея пришла вобще то давно ) shr eax,33 - 1 байт 8 бит - макс значение в 32 битном регистре(DWORD = 4 байтам или 32 бита),следовательно сдвинув регистр на 33 мы получим 0
Ещё можно сделать так. Запустить netcat на удаленном unix-хосте взломаном, приконектится со своего компа туда telnet'ом и послать единицу, а там руткит перехватит её в траффике, преобразует в число и засунет в регистр. Заодно потом в консоли можно на ascii-порнуху подрочить, за заслуги, как все настоящии хакеры по манифесту (вместо стандарта).