Здравствуйте товарищи ассемблерщики. Увлекаюсь ассемблером несколько месяцев. Использую FASM. Решил перевести небольшую функцию с C++ в асм код. Но как всегда грабли, граааабли... Вот собственно процедура: Код (Text): DWORD RQ_GetINTLIST(BYTE * bArr, DWORD * iPos, DWORD iLen, DWORD * iListLen, int ** pList) { DWORD iLLen,i; if ((*iPos+4)>iLen) return 1; memcpy(&iLLen,bArr+*iPos,4); *iPos+=4; i = (iLen-*iPos)/4; if (i>=iLLen) iLLen = i; *pList = (int*)(bArr+*iPos); *iPos += iLLen*4; *iListLen = iLLen; return 0; } Получилось вот что: Код (Text): proc RQ_GetINTLIST bArr, iPos, iLen, iListLen, pList ; BYTE *, DWORD *, DWORD, DWORD * , int ** locals dw iLLen endl pushad mov eax, iLen add eax, 4 cmp [iPos], eax jg .return_false mov eax, bArr add eax, [iPos] mov DWORD iLLen, [eax] add DWORD [iPos], 4 mov eax, iLen sub eax, [iPos] shr eax, 2 cmp eax, iLLen jl .next mov iLLen, eax .next: mov eax, bArr add eax, [iPos] mov [pList], eax mov eax, iLLen imul eax, 4 mov [iPos], eax mov eax, iLLen mov [iListLen], eax .return: popad xor eax, eax ret .return_false popad mov eax, 1 ret endp Ногами не бить, я уверен что правильно написаны тут лишь опкоды Собственно начав тестировать пример, я наткнулся на ошибки. Почему я немогу пользоваться локальными переменными и аргументиами переданными функции как любыми другими, определенными, например, в секции данных? Тоесть mov iLLen, eax и наоборот неполучается =) Нужно обязательно [iLLen]. А тут я подумал, а вдруг в этих переменных содержатся адреса на реальные данные, которые должны находится в этих переменных. И доступ кним тольько яерез []. Но а как же быть если в переменной iPos должен храниться адрес на определенный участок памяти, и доступ к этому участку памяти должен быть через [], но там храниться адрес в памяти, указывающий на реальный адрес который должен быт ьв переменной, но насколько я знаю что оператора [[]] нету пока в фасме =) И вот товарищи знатоки, пожалуйста, рассейте мои сомнения, скажите же что все вышенаписанное всего лишь бред пьяного, бородатого, неопытного, начинающего (!!!) ассемблерщика, и укажите же мне истеный путь PS и еще процедурку пожалуйста с каментами перепишите, конечно же если вас это не затруднит =) Заранее спасибо =)
gentr0 По поводу адреса памяти указывающего на адрес - все оч просто Допустим в iPos содержится адрес тогда: mov eax,[iPos] mov eax,[eax] В итоге в eax лежит данные по нужному адресу. И не надо никаких [[]]. Проявите изобретательность. Да и не злоупотребляйте переменными, если их немного, то вообще можно юзать только регистры и стек. А переписывать некогда. Может вечером, если никто больше не ответит. А вообще - неужели сложно глянуть асм код, который сгенерировала студия из С++ кода?
Код (Text): ;DWORD RQ_GetINTLIST(BYTE * bArr, DWORD * iPos, DWORD iLen, DWORD * iListLen, int ** pList) RQ_GetINTLIST: push ebp mov ebp, esp sub ebp, 0x4 push ebx mov eax, [ebp + 0xC] ;в eax лежит адрес iPos. mov eax, [eax] ;в eax лежит значение iPos. add eax, 0x4 ;прибавляем к локальной копии iPos 4. cmp eax, [ebp + 0x10] ;сравниваем (iPos + 4) с (iLen). jbe @f mov eax, 0x1 ;(iPos + 4) > iLen, кладем в eax 1 и прыгаем на выход из процедуры. jmp .locret @@: mov edx, [ebp + 0x8] ;кладем в edx адрес bArr mov ecx, [edx + eax - 0x4] ;кладем в ecx [bArr + *iPos]. -4 нужно потому, что до этого мы прибавили к iPos 4. mov [ebp - 0x4], ecx ;сохраняем полученное значение в переменной iLLen. mov edx, [ebp + 0xC] ;в edx адрес iPos mov [edx], eax ;сохраняем в iPos значение "iPos + 4" посчитанное ранее. mov ebx, eax ;спасем iPos, он нам еще пригодится. sub eax, [ebp + 0x10] ;вычитаем из iPos значение iLen neg eax ;т.к. мы поменяли операнды местами, надо сменить знак. mov ecx, 0x4 ;готовимся к делению. xor edx, edx ;DWORD, если я не ошибаюсь, беззнаковый. Значит обнулим edx перед делением. mov ebx, eax ;спасем iPos, он нам еще пригодится. div ecx ;в eax результат деления, в edx -- остаток cmp eax, [ebp - 0x4] jb @f mov [ebp - 0x4], eax ;если i (он же eax) >= iLLen, то присвоим iLLen значение i. @@: mov eax, [ebp + 0x8] ;в eax адрес bArray mov eax, [eax + ebx * 4] ;в eax (int*)(bArr+*iPos) mov ecx, [ebp + 0x18] ;в ecx адрес адреса pList mov [ecx], eax ;*pList = (int*)(bArr+*iPos) mov eax, [ebp - 0x4] ;готовимся к умножению на 4 mov ecx, 4 mul ecx add ebx, eax ;прибавляему "iLLen * 4" к iPos mov eax, [ebp + 0xC];в eax адрес iPos mov [eax], ebx ;сохраняем iPos mov ecx, [ebp - 0x4] mov eax, [ebp + 0x14] mov [eax], ecx ;*iListLen = iLLen xor eax, eax ;return 0; .locret: pop ebx add esp, 0x4 pop ebp ret Не ассемблировал, не проверял, но, вроде, верно . Конвенция cdecl.
gentr0 iLLen dd ? остальной код не смотрел, это первое что бросилось в глаза. Не знаю, почему ты не можешь. Локальные переменные и аргументы в стеке ничем не хуже данных, определенных в секции данных. ты хочешь в переменную iLLen положить eax? если да, то надо писать mov [iLLen],eax. Наоборот: mov eax,[iLLen]. для DWORD * iPos: Код (Text): mov eax,[iPos] mov eax,[eax] ; в eax будет dword, на который указывает iPos. для int ** pList: Код (Text): mov eax,[pList] mov eax,[eax] mov eax,[eax] ; в eax будет int (считаю, что он 32-битный), на который указывает pList. последние 3 слова меня убили... Начни с начала. С учебников Зубкова и Юрова.
У меня нету студии, а также скомпиленного бинарника =) Пожалуйста не стоит придираться к словам. Это было шуткой, если ты не заметил =) Читал, непонравилось. Не очень меня вдохновило творчество этих авторов. И вообще, я предпочитаю обучаться не по книгам, а на практике. Создать определенную задачу, и выполнять её ,обучаясь тем временем новым приемам и тд. А лучшие учебники для меня - яндекс, гугл. И вообще, meduza, попроще, попроще) Спс, щас гляну =) Гг, тут чото я тупанул =) После С кода автоматом наверное написал =)
2 meduza Я имел в виду что Код (Text): format PE GUI 4.0 include '%fasminc%/win32ax.inc' section '.data' data readable writeable var0 dd ? section '.code' code readable executable start: mov [var0], 0xFF mov eax, var0;----------------------------------------можно mov eax, [var0] push var0 push [var0] call MyProc0 push 0 call [ExitProcess] proc MyProc0 var1, var2 locals var3 dd ? endl mov eax, var1;--------------------------------ошибка mov ebx, [var1] mov edx, [var2] ret endp .end start А потом я наконец понял что proc - это макрос И переменные это область стека Кстати спасибо Mika0x65, намекнул Вот щас думаю, как я так кодил не зная даже того что proc это макрос /me пошел перечитывать fasm.pdf Всем спасибо, всё что нужно выяснил =)
gentr0 Так происходит потому, что перменная в стеке адресуется относительно ebp, например, 'ebp - 0x4'. Соответсвтенно, когда ты пишешь 'mov eax, var1', то это подменяется на 'mov eax, ebp - 0x4', что недопустимо. Чтобы получить значение переменной надо поставить квадратные скобки: 'mov eax, [var1]'. А чтобы получить адрес -- использовать инструкцию 'lea'. А вообще, на первых порах макросов лучше избегать, как мне кажется.
Mika0x65 Ага, про lea уже проходили =) А в макросы я без надобности пока стараюсь не лезть =) Читаю потихоньку про макроязык фасма =)