Как работает LEA

Тема в разделе "WASM.BEGINNERS", создана пользователем MrBean, 29 май 2007.

  1. MrBean

    MrBean New Member

    Публикаций:
    0
    Регистрация:
    29 май 2007
    Сообщения:
    4
    День добрый!

    Вот понадобилось строку в число конвертировать, взял МАСМовскую atodw, немного изменил (убрал проверку на минус, мне это не понадобится, и переделал под UNICODE), и вот что получилось:
    Код (Text):
    1. StrToInt proc
    2.  xor  eax, eax
    3.  xor  ecx, ecx
    4.  mov  ax, [edx]
    5.  add  edx, 2
    6.  jmp  L1
    7. L0:
    8.  sub  ax, 30h
    9.  lea  ecx, [ecx+ecx*4]
    10.  lea  ecx, [eax+ecx*2]
    11.  mov  ax, [edx]
    12.  add  edx, 2
    13. L1:
    14.  test ax, ax
    15.  jnz  L0
    16.  lea  eax, [ecx]
    17.  retn
    18. StrToInt endp
    указатель на строку передаю в EDX. Всё чудесно, но радость несколько омрачается полным непониманием того, как она работает =( Знаю, что для конвертирования нужно из кода символа вычесть код символа 0 (30h) и умножить на 10 в степени <кол-во символов минус позиция>. Всё вроде прозрачно, но как всё эту работу делают две команды LEA? Тут вообще нигде не определятся количество символов, непонятно где тут счётчик позиции! Расскажите, пожалуйста, как всё это работет и посоветуйте умные книжки, где рассказано как можно овладеть таким кунг-фу =)
     
  2. MHajduk

    MHajduk New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2006
    Сообщения:
    123
    Код (Text):
    1. lea  ecx, [ecx+ecx*4] ; ecx := ecx + 4*ecx  т.е. ecx := 5*ecx
    2. lea  ecx, [eax+ecx*2] ; ecx := eax + 2*ecx т.е. ecx := eax + 10*ecx
    Надеюсь, что я прав. :)
     
  3. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    MrBean
    Тут заложена простая рекуррентная формула - выпиши ее и все поймешь.
     
  4. MrBean

    MrBean New Member

    Публикаций:
    0
    Регистрация:
    29 май 2007
    Сообщения:
    4
    Да, действительно, разложил по кусочкам, посчитал всё на бумажке, и стало понятно! Непонятно только, как кто-то додумался до такой замечательной формулы =D MHajduk, crypto, спасибо!
     
  5. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    MrBean
    Рекуррентность - чрезвычайно мощный инструмент, широко используемый в математике (ну и в программировании тоже, ес-но).
     
  6. MrBean

    MrBean New Member

    Публикаций:
    0
    Регистрация:
    29 май 2007
    Сообщения:
    4
    Непременно познакомлюсь с рекуррентностью, но чуть позже. У меня ещё вопрос по теме конвертирования строк и чисел. Вот уже самостоятельно набросал функцию перевода числа в строку:
    Код (Text):
    1. IntToStr proc
    2.  mov  ecx, 10
    3. @@:
    4.  cdq
    5.  idiv ecx
    6.  add  edx, 30h
    7.  mov  [ebx], dx
    8.  add  ebx, 2
    9.  test eax, eax
    10.  jnz  @b
    11.  mov  [ebx], ax
    12.  retn
    13. IntToStr endp
    число передаётся в EAX, указатель на буфер в EBX
    Пара вопросов по ней. Не обращая внимания на то, что число в строке отображается зеркально =D (это мы починим, я думаю, нет смысла двигать слова внутри цикла, лучше это сделать после, или есть способ лучше?), что можно в ней подправить?
    Что здесь уместнее cdq или xor edx, edx?
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    MrBean
    Вообще-то в данном случае неизвестно значение eax, поэтому cdq и xor edx, edx здесь не эквивалентны.
    Хотя... мож как всегда чушь несу. :)
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Раз знак не учитывается, то нужно xor edx,edx / div ecx.
     
  9. nobodyzzz

    nobodyzzz New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2005
    Сообщения:
    475
    l_inc
    ну вообще-то cdq здесь используеться не как эквивалент xor edx, edx...
    Код (Text):
    1. IDIV performs a signed division. The dividend,
    2. quotient, and remainder are implicitly allocated to fixed registers.
    3. Only the divisor is given as an explicit r/m operand.
    4. The type of the divisor determines which registers to use as follows:
    5.  
    6. Size     Divisor    Quotient    Remainder  Dividend
    7. byte     r/m8        AL           AH       AX
    8. word     r/m16       AX           DX       DX:AX
    9. dword    r/m32       EAX          EDX      EDX:EAX
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    nobodyzzz
    Я о том и говорю, что они не эквивалентны.
    И учитывая вопрос
    очевидно, что для знакового деления здесь xor edx, edx не подойдет, а для беззнакового cdq не подойдет. Я же просто написал, что они не эквивалентны, отвечая на вопрос.
     
  11. Yaroslav

    Yaroslav New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    3
    Спасибо, учту все замечания. Знак меня действительно не интересует. Вот ещё немного кода. Попытка решить проблему зеркального отображения строки. Не функция, просто код "переварачивающий" число. Собираюсь вставить его в начало функции IntToStr.
    Код (Text):
    1.  mov  eax, 12345
    2.  mov  ecx, 10
    3.  xor  ebx, ebx
    4. @@:
    5.  xor  edx, edx
    6.  div ecx
    7.  lea  ebx, [ebx+ebx*4]
    8.  shl  ebx, 1
    9.  add  ebx, edx
    10.  test eax, eax
    11.  jnz  @b
    ;в EBX 54321
    какие здесь замечания?

    ---
    upd Это я же, просто случайно отписал с аккаунта брата. Он разлогиниться забыл, а я не заметил =)
     
  12. MrBean

    MrBean New Member

    Публикаций:
    0
    Регистрация:
    29 май 2007
    Сообщения:
    4
    Всё, полностью разобрался в вопросе, всё понял. Всем, принимавшим участие в обсуждении, огромное спасибо и респект! Вопросов больше не имею.
     
  13. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    Yaroslav
    код shl ebx, 1/ add ebx, edx (D1E3 03DA - 4 байта) эквивалентен lea ebx,[ebx*2+edx] (8D1C5A - 3 байта)