StrToInt

Тема в разделе "WASM.BEGINNERS", создана пользователем FakeMan, 19 июн 2008.

  1. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Вот есть такая ф-я, написанная в целях оптимизации
    Код (Text):
    1. function StrToInt ( Str : PChar ) : Cardinal;
    2. asm
    3.     mov esi, eax //?
    4.     xor eax, eax //?
    5.     cdq
    6. @loop:
    7.     lodsb
    8.     sub    al, 48
    9.     jb     @done
    10.     imul   edx, 10
    11.     add    edx, eax
    12.     jmp    @loop
    13. @done:
    14.     mov eax, edx //?
    15.     ret
    16. end;
    Но т.к. я совсем не знаток Asm'a, то неуверен насчет правильности строк помеченных "//?".
    Скажите пожайлуста, этот код не будет сбоить?
    Может есть еще более короткий вариант?
     
  2. Twister

    Twister New Member

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    720
    Адрес:
    Алматы
    Еще меньше можно: http://twister.rootkits.ru/notes.php#n_smint2str (в название ссылки не смотри - влом править было)
     
  3. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Вообщето это и есть твой код, только слегка измененный, дабы использовать его в Delphi программах. Так как изменял я, то спрашиваю, правильно сделал али нет
     
  4. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    function StrToInt ( Str : PChar ) : Cardinal;
    asm
    mov esi, Str
    xor eax, eax
    cdq
    @loop:
    lodsb
    sub al, 48
    jb @done
    imul edx, 10
    add edx, eax
    jmp @loop
    @done:
    mov Result, edx // всётки делфе.. лучше предостерегусь.
    ret
    end;

    вотак. кстате "SMALLEST STR2INT" - смелое заявление .))
    я бы сказал, слишком.
     
  5. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    В дельфи-программах нужна оптимизация по размеру вплоть до байта ?!!
    Лучше бы из дельфийской _ValLong выдрал бы кусок, исключив лишние проверки ;)

    Нет, регистр esi нужно сохранять и восстанавливать при выходе из функции - а это лишних 2 байта, о ужо-о-с !! :lol:
     
  6. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Comer_
    У ТС видимо аргумент передается через регистр.
     
  7. random

    random New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2008
    Сообщения:
    38
    Я писал так: (параметры через стек не передавал, а так - аргумент (указатель на строку) в esi, результат в edi... Еще один момент - я точно знал что отдаю число определенной разрядности, поэтому использовал loop и не использовал проверку валидности
    Код (Text):
    1.  Str2Int proc
    2.               xor eax,eax
    3.               xor edi,edi
    4.               mov ecx,SIZE_NUM
    5. nxt:
    6.              lea edi,[edi*4+edi]
    7.              lea edi,[edi*2+eax]
    8.              lodsb
    9.              xor eax,30h
    10.              loop nxt
    11.             ret
    12.             Str2Int endp
     
  8. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    crypto
    аа...
    ну тогда вобще смысел юзать делфи? =\
    чтобы хекакод смотрелся мегахеком?
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Думать нужно немного прежде чем копи-пастить ;) Ради 1-байтной тормозной lodsb тебе придется добавить еще 4 байта на mov\push\pop esi - итого 5 байт, хотя по простому достаточно 3 байт mov+inc. Плюс мелочная экономия на imul+add дает выигрыш в 1 байт по сравнению с двумя lea, но зато заметно тормознее особенно на P4. К тому же если экономить байты, то незачем юзать два перехода jb+jmp, если можно обойтись одним, переставив местами загрузку символа и вычисление результата ;)

    Вот для примера простой вариант без мелочной экономии (ес-но без доп.проверок недопустимые символы, включая знак минус)
    Код (Text):
    1. function MyStrToInt(S:pChar):cardinal;register;
    2. //eax = S
    3. asm
    4.   xor edx,edx
    5.   xor ecx,ecx
    6. @@loop:
    7.   lea ecx,[ecx+ecx*4] //ecx:=ecx*5
    8.   lea ecx,[edx+ecx*2] //ecx:=ecx*2+edx
    9.   mov dl,[eax]
    10.   inc eax
    11.   sub dl,'0'
    12.   jnc @@loop
    13.   mov eax,ecx
    14. end;
     
  10. random

    random New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2008
    Сообщения:
    38
    А вообще в MASM в каталоге m32lib лежит прелюбопытнейший файл, называется atodw.asm
    Код (Text):
    1. atodw proc String:DWORD
    2.  
    3.   ; ----------------------------------------
    4.   ; Convert decimal string into dword value
    5.   ; return value in eax
    6.   ; ----------------------------------------
    7.  
    8.     push esi
    9.     push edi
    10.  
    11.     xor eax, eax
    12.     mov esi, [String]
    13.     xor ecx, ecx
    14.     xor edx, edx
    15.     mov al, [esi]
    16.     inc esi
    17.     cmp al, 2D
    18.     jne proceed
    19.     mov al, byte ptr [esi]
    20.     not edx
    21.     inc esi
    22.     jmp proceed
    23.  
    24.   @@:
    25.     sub al, 30h
    26.     lea ecx, dword ptr [ecx+4*ecx]
    27.     lea ecx, dword ptr [eax+2*ecx]
    28.     mov al, byte ptr [esi]
    29.     inc esi
    30.  
    31.   proceed:
    32.     or al, al
    33.     jne @B
    34.     lea eax, dword ptr [edx+ecx]
    35.     xor eax, edx
    36.  
    37.     pop edi
    38.     pop esi
    39.  
    40.     ret
    41.  
    42. atodw endp
    тока я б тут если не lodsb, то хотя бы movzx заюзал вместо mov
     
  11. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    2 leo Спасибо. Про директиву компилятора register я совсем забыл... Эта кажется самое большая ошибка в этих 10 строках :dntknw:
    Видимо компилятор просто в процессе оптимизации делал все как надо. ( ибо на первый взгляд работало )
     
  12. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
  13. Twister

    Twister New Member

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    720
    Адрес:
    Алматы
    Comer_
    Осилишь меньший размер? Просто убрать cdq не в счет... ;)
     
  14. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    FakeMan
    В дельфях и так по умолчанию юзается register, иначе бы твоя функция вообще бы не работала. А "самая большая ошибка" - это затирание esi. По общему правилу можно изменять только eax, edx и ecx, а если юзаешь другие регистры, то их нужно сохранять и восстанавливать перед выходом из функции

    Twister
    Переставь imul+add в начало цикла и убери лишний jmp
    PS: Гордиться минимальным размером при нестандартной конвенции вызова - мягко говоря, не честно ;)
     
  15. bugaga

    bugaga New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2007
    Сообщения:
    361
    Реверс асм кода на дельфе:
    Код (Text):
    1. {$APPTYPE CONSOLE}
    2. program test;
    3.  
    4. function StrToInt (Str:PChar):Cardinal;
    5. var
    6.     ch:^byte;
    7. begin
    8.     Result := 0;
    9.     ch := pointer(str);
    10. repeat
    11.    Result := Result * 10 + (ch^-48);
    12.    inc(ch);
    13. until ch^ = 0;
    14. end;
    15.  
    16. begin
    17. writeln (integer(StrToInt ('1234567890')));
    18. end.
    и как его оформил компиль:
    Код (Text):
    1. -.00401C7C: 33D2         xor         edx,edx
    2. -.00401C7E: 03D2         add         edx,edx
    3. -.00401C80: 8D1492       lea         edx,[edx][edx]*4
    4. -.00401C83: 0FB608       movzx       ecx,b,[eax]
    5. -.00401C86: 83E930       sub         ecx,030 ;
    6. -.00401C89: 03D1         add         edx,ecx
    7. -.00401C8B: 40           inc         eax
    8. -.00401C8C: 803800       cmp         b,[eax],000
    9. -.00401C8F: 75ED         jne        .000401C7E  
    10. -.00401C91: 8BC2         mov         eax,edx
    11. -.00401C93: C3           retn
    лепота :)
     
  16. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Спасибо, учту.