Перевод функции (C++ to FASM) + пара вопросов =)

Тема в разделе "WASM.BEGINNERS", создана пользователем gentr0, 10 дек 2008.

  1. gentr0

    gentr0 New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2008
    Сообщения:
    4
    Здравствуйте товарищи ассемблерщики. Увлекаюсь ассемблером несколько месяцев. Использую FASM. Решил перевести небольшую функцию с C++ в асм код. Но как всегда грабли, граааабли... Вот собственно процедура:
    Код (Text):
    1. DWORD RQ_GetINTLIST(BYTE * bArr, DWORD * iPos, DWORD iLen, DWORD * iListLen, int ** pList)
    2. {
    3.     DWORD iLLen,i;
    4.     if ((*iPos+4)>iLen) return 1;
    5.     memcpy(&iLLen,bArr+*iPos,4);
    6.     *iPos+=4;
    7.     i = (iLen-*iPos)/4;
    8.    
    9.     if (i>=iLLen) iLLen = i;
    10.     *pList = (int*)(bArr+*iPos);
    11.     *iPos += iLLen*4;
    12.     *iListLen = iLLen;
    13.     return 0;
    14. }
    Получилось вот что:
    Код (Text):
    1. proc    RQ_GetINTLIST   bArr, iPos, iLen, iListLen, pList   ; BYTE *, DWORD *, DWORD, DWORD * , int **
    2.    
    3.     locals
    4.         dw  iLLen
    5.     endl
    6.    
    7.     pushad
    8.    
    9.     mov eax, iLen
    10.     add eax, 4
    11.     cmp [iPos], eax
    12.     jg  .return_false
    13.     mov eax, bArr
    14.     add eax, [iPos]
    15.     mov DWORD iLLen, [eax]
    16.     add DWORD [iPos], 4
    17.     mov eax, iLen
    18.     sub eax, [iPos]
    19.     shr eax, 2
    20.     cmp eax, iLLen
    21.     jl  .next
    22.     mov iLLen, eax
    23.     .next:
    24.         mov eax, bArr
    25.         add eax, [iPos]
    26.         mov [pList], eax
    27.         mov eax, iLLen
    28.         imul    eax, 4
    29.         mov [iPos], eax
    30.         mov eax, iLLen
    31.         mov [iListLen], eax
    32.        
    33.         .return:
    34.             popad
    35.             xor eax, eax
    36.             ret
    37.         .return_false
    38.             popad
    39.             mov eax, 1
    40.             ret
    41. endp
    Ногами не бить, я уверен что правильно написаны тут лишь опкоды :lol:
    Собственно начав тестировать пример, я наткнулся на ошибки. Почему я немогу пользоваться локальными переменными и аргументиами переданными функции как любыми другими, определенными, например, в секции данных?
    Тоесть mov iLLen, eax и наоборот неполучается =) Нужно обязательно [iLLen]. А тут я подумал, а вдруг в этих переменных содержатся адреса на реальные данные, которые должны находится в этих переменных. И доступ кним тольько яерез []. Но а как же быть если в переменной iPos должен храниться адрес на определенный участок памяти, и доступ к этому участку памяти должен быть через [], но там храниться адрес в памяти, указывающий на реальный адрес который должен быт ьв переменной, но насколько я знаю что оператора [[]] нету пока в фасме =)
    И вот товарищи знатоки, пожалуйста, рассейте мои сомнения, скажите же что все вышенаписанное всего лишь бред пьяного, бородатого, неопытного, начинающего (!!!) ассемблерщика, и укажите же мне истеный путь ;)
    PS и еще процедурку пожалуйста с каментами перепишите, конечно же если вас это не затруднит =)
    Заранее спасибо =)
     
  2. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.568
    Адрес:
    Russia
    gentr0
    По поводу адреса памяти указывающего на адрес - все оч просто
    Допустим в iPos содержится адрес тогда:
    mov eax,[iPos]
    mov eax,[eax]
    В итоге в eax лежит данные по нужному адресу. И не надо никаких [[]]. Проявите изобретательность.
    Да и не злоупотребляйте переменными, если их немного, то вообще можно юзать только регистры и стек.
    А переписывать некогда. Может вечером, если никто больше не ответит.
    А вообще - неужели сложно глянуть асм код, который сгенерировала студия из С++ кода?
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Код (Text):
    1. ;DWORD RQ_GetINTLIST(BYTE * bArr, DWORD * iPos, DWORD iLen, DWORD * iListLen, int ** pList)
    2. RQ_GetINTLIST:
    3.  push ebp
    4.  mov ebp, esp
    5.  sub ebp, 0x4
    6.  push ebx
    7.  mov eax, [ebp + 0xC] ;в eax лежит адрес iPos.
    8.  mov eax, [eax] ;в eax лежит значение iPos.
    9.  add eax, 0x4 ;прибавляем к локальной копии iPos 4.
    10.  cmp eax, [ebp + 0x10] ;сравниваем (iPos + 4) с (iLen).
    11.  jbe @f
    12.   mov eax, 0x1 ;(iPos + 4) > iLen, кладем в eax 1 и прыгаем на выход из процедуры.
    13.   jmp .locret
    14. @@:
    15.  mov edx, [ebp + 0x8] ;кладем в edx адрес bArr
    16.  mov ecx, [edx + eax - 0x4] ;кладем в ecx [bArr + *iPos]. -4 нужно потому, что до этого мы прибавили к iPos 4.
    17.  mov [ebp - 0x4], ecx ;сохраняем полученное значение в переменной iLLen.
    18.  mov edx, [ebp + 0xC] ;в edx адрес iPos
    19.  mov [edx], eax ;сохраняем в iPos значение "iPos  + 4" посчитанное ранее.
    20.  mov ebx, eax ;спасем iPos, он нам еще пригодится.
    21.  sub eax, [ebp + 0x10] ;вычитаем из iPos значение iLen
    22.  neg eax ;т.к. мы поменяли операнды местами, надо сменить знак.
    23.  mov ecx, 0x4 ;готовимся к делению.
    24.  xor edx, edx ;DWORD, если я не ошибаюсь, беззнаковый. Значит обнулим edx перед делением.
    25.  mov ebx, eax ;спасем iPos, он нам еще пригодится.
    26.  div ecx ;в eax результат деления, в edx -- остаток
    27.  cmp eax, [ebp - 0x4]
    28.  jb @f
    29.   mov [ebp - 0x4], eax ;если i (он же eax) >= iLLen, то присвоим iLLen значение i.
    30. @@:
    31.  mov eax, [ebp + 0x8] ;в eax адрес bArray
    32.  mov eax, [eax + ebx * 4] ;в eax (int*)(bArr+*iPos)
    33.  mov ecx, [ebp + 0x18] ;в ecx адрес адреса pList
    34.  mov [ecx], eax ;*pList = (int*)(bArr+*iPos)
    35.  mov eax, [ebp - 0x4] ;готовимся к умножению на 4
    36.  mov ecx, 4
    37.  mul ecx
    38.  add ebx, eax ;прибавляему "iLLen * 4" к iPos
    39.  mov eax, [ebp + 0xC];в eax адрес iPos
    40.  mov [eax], ebx ;сохраняем iPos
    41.  mov ecx, [ebp - 0x4]
    42.  mov eax, [ebp + 0x14]
    43.  mov [eax], ecx ;*iListLen = iLLen
    44.  xor eax, eax ;return 0;
    45.  
    46. .locret:
    47.  pop ebx
    48.  add esp, 0x4
    49.  pop ebp
    50.  ret
    Не ассемблировал, не проверял, но, вроде, верно :). Конвенция cdecl.
     
  4. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    gentr0
    iLLen dd ?
    остальной код не смотрел, это первое что бросилось в глаза.

    Не знаю, почему ты не можешь. Локальные переменные и аргументы в стеке ничем не хуже данных, определенных в секции данных.

    ты хочешь в переменную iLLen положить eax? если да, то надо писать mov [iLLen],eax. Наоборот: mov eax,[iLLen].

    для DWORD * iPos:
    Код (Text):
    1. mov eax,[iPos]
    2. mov eax,[eax] ; в eax будет dword, на который указывает iPos.
    для int ** pList:
    Код (Text):
    1. mov eax,[pList]
    2. mov eax,[eax]
    3. mov eax,[eax] ; в eax будет int (считаю, что он 32-битный), на который указывает pList.
    последние 3 слова меня убили...

    Начни с начала. С учебников Зубкова и Юрова.
     
  5. gentr0

    gentr0 New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2008
    Сообщения:
    4
    У меня нету студии, а также скомпиленного бинарника =)
    Пожалуйста не стоит придираться к словам. Это было шуткой, если ты не заметил =)
    Читал, непонравилось. Не очень меня вдохновило творчество этих авторов. И вообще, я предпочитаю обучаться не по книгам, а на практике. Создать определенную задачу, и выполнять её ,обучаясь тем временем новым приемам и тд. А лучшие учебники для меня - яндекс, гугл.
    И вообще, meduza, попроще, попроще)
    Спс, щас гляну =)
    Гг, тут чото я тупанул =) После С кода автоматом наверное написал =)
     
  6. gentr0

    gentr0 New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2008
    Сообщения:
    4
    2 meduza
    Я имел в виду что
    Код (Text):
    1. format PE GUI  4.0
    2. include   '%fasminc%/win32ax.inc'
    3. section '.data' data readable writeable
    4. var0    dd      ?
    5. section '.code' code readable executable
    6. start:
    7. mov     [var0], 0xFF
    8. mov     eax,  var0;----------------------------------------можно
    9. mov     eax, [var0]
    10. push    var0
    11. push    [var0]
    12. call    MyProc0
    13. push    0
    14. call    [ExitProcess]
    15. proc    MyProc0 var1, var2
    16. locals
    17. var3    dd      ?
    18. endl
    19.  
    20. mov eax, var1;--------------------------------ошибка
    21. mov     ebx, [var1]
    22.  
    23. mov     edx, [var2]
    24. ret
    25. endp
    26. .end start
    А потом я наконец понял что proc - это макрос :lol: :lol: :lol: И переменные это область стека :lol: :lol: :lol: Кстати спасибо Mika0x65, намекнул ;)
    Вот щас думаю, как я так кодил не зная даже того что proc это макрос :lol: :lol:
    /me пошел перечитывать fasm.pdf
    Всем спасибо, всё что нужно выяснил =)
     
  7. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    gentr0
    Так происходит потому, что перменная в стеке адресуется относительно ebp, например, 'ebp - 0x4'. Соответсвтенно, когда ты пишешь 'mov eax, var1', то это подменяется на 'mov eax, ebp - 0x4', что недопустимо. Чтобы получить значение переменной надо поставить квадратные скобки: 'mov eax, [var1]'. А чтобы получить адрес -- использовать инструкцию 'lea'.

    А вообще, на первых порах макросов лучше избегать, как мне кажется.
     
  8. gentr0

    gentr0 New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2008
    Сообщения:
    4
    Mika0x65
    Ага, про lea уже проходили =) А в макросы я без надобности пока стараюсь не лезть =) Читаю потихоньку про макроязык фасма =)