Объясните пжл как работает этот код

Тема в разделе "WASM.BEGINNERS", создана пользователем gershkovich, 20 ноя 2006.

  1. gershkovich

    gershkovich New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2006
    Сообщения:
    97
    Вытащил откуда не помню проц-у для кодирования Base 64.
    Давно ею пользуюсь и считал что все ок пока не мне не
    понадобилось возвращать последнее значение EDI

    Я заношу его значение в EAX (строчка в коде помеченая ; Return the address of last byte)

    НО до этого места проц-а не доходит !!!!
    Несмотря на то что я сохраняю в стэке еще регистры
    (push esi edi edx ebx), на момент возврата стэк
    корректен - проц-а возвращается в точку вызова основной программы

    Причем возврат происходит не там где я ожидал, а в другом месте
    (помечено ; ВОЗВРАТ ПРОИСХОДИТ ЗДЕСЬ )

    Причем в коде нигде не производится операции со стеком!

    Что за чудеса ?
    Бьюсь целый день, никаких мыслей

    Заранее спасибо за разъяснение.

    Код (Text):
    1. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2. ; base64 encoder without dictionary by RT Fishel
    3. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    4. proc Base64Encode lpSrc, lpDst, dwstrlen
    5.         push        esi edi edx ebx
    6.                      
    7.         mov         esi, [lpSrc]
    8.         mov         edi, [lpDst]
    9.         mov         ebx, dword [dwstrlen]
    10.         call        b64.encode
    11.  
    12.         ; Return the address of last byte
    13.         mov         eax, edi
    14.  
    15.         pop         ebx edx edi esi
    16.         ret
    17.  
    18.  
    19.   b64:      
    20.     .newline:
    21.         call        b64.store_crlf
    22.                      
    23.     .encode:
    24.         push        (76 shr 2) + 1
    25.         pop         edx
    26.                      
    27.     .outer:    
    28.         dec         edx
    29.         je          b64.newline
    30.         lodsd
    31.         dec         esi
    32.         inc         ebx
    33.         bswap       eax
    34.         mov         ecx, 4
    35.                      
    36.     .inner:    
    37.         rol         eax, 6
    38.         and         al, 3Fh
    39.         cmp         al, 3Eh
    40.         jb          b64.testchar
    41.         shl         al, 2
    42.         sub         al, ((3Eh shl 2) + 'A' - '+') and 0FFh
    43.                      
    44.     .testchar:
    45.         sub         al, 4
    46.         cmp         al, '0'
    47.         jnl         b64.store
    48.         add         al, 'A' + 4
    49.         cmp         al, 'Z'
    50.         jbe         b64.store
    51.         add         al, 'a' - 'Z' - 1
    52.                      
    53.     .store:    
    54.         stosb
    55.         dec         ebx
    56.         loopne      b64.inner
    57.         jne         b64.outer
    58.         mov         al, '='
    59.         rep         stosb
    60.         xor         al, al
    61.         stosb
    62.  
    63. ; ВОЗВРАТ ПРОИСХОДИТ ЗДЕСЬ
    64.         ret
    65.  
    66.     .store_crlf:
    67.         mov         ax, 0a0dh
    68.         stosw
    69.                      
    70.         ret
    71. endp
     
  2. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    proc/endp говорят компилятору, что все, что между ними - одна процедура. Причём у неё есть 3 параметра, так что компилятор неявно генерирует код пролога и эпилога: в начале push ebp/mov ebp,esp и перед каждым ret вставляет leave (или mov esp,ebp/pop ebp, в данном контексте неважно) и, возможно, заменяет ret на ret 12 (если модель вызова stdcall). Соответственно первый же ret приводит к выходу из всей процедуры, а не возврат из call b64.
    P.S. Компилятор, судя по конструкциям, FASM? Тогда работу выполняет не сам компилятор, а proc/endp - макросы, исходный код которых даже можно посмотреть.
     
  3. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Видимо ты попался в сети убого масмодобия ;)
    Попробуй заменить все ret после b64 на retn или оформи b64 в виде proc
     
  4. gershkovich

    gershkovich New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2006
    Сообщения:
    97
    Спасибо

    Посмотрел в отладчике - так оно и есть...
    ENTER и LEAVE