![]() |
|
|
#1
|
||||
|
||||
|
Подскажите, как на фасме проще забабахать простейший связный список.
В голову кроме извращений с Alloc'ами ничего не приходит. Или как та же виЖуал студия их реализует(ща нет возможности в визуал студию зайти)? |
|
#2
|
||||
|
||||
|
Вообще простейший список - да, куча аллоков.
Однако STL вроде бы выделяет блок памяти и размечает в нем список, потом с ним работает. Если становится мало - выделяет еще один и размечает его. По крайней мере так было когда я не заметил, как ревершу список в одной проге. Простейший же список я делал на фасме через постоянный маллок. Структурка вида Код:
struc List
{
.Next dd 0
.Data dd 0
.size = $ - .Next
} |
|
#3
|
||||
|
||||
|
Набабахал (путем рипа из дельфи) некое подобие связного списка.
Код:
format PE GUI 4.0
entry start
use32
include 'win32a.inc'
section '.text' code readable executable
proc InsertItem
Result = -4
AParent = 8
AData = 0Ch
push ebp
mov ebp, esp
sub esp, 4
invoke LocalAlloc, 40h, 0Ch ; 0Ch - size of struct
mov [ebp+Result], eax
xor edx, edx
mov eax, [ebp+Result]
mov [eax], edx
mov eax, [ebp+Result]
mov [eax+4], edx
mov eax, [ebp+Result]
mov edx, [ebp+AData]
mov [eax+8], edx
cmp dword [ebp+AParent], 0 ; if1
jz InsertItem_if1end
mov eax, [ebp+Result]
mov edx, [ebp+AParent]
mov [eax], edx
mov eax, [ebp+AParent]
cmp dword [eax+4], 0 ; if2
jz InsertItem_if2else
mov eax, [ebp+Result]
mov edx, [ebp+AParent]
mov edx, [edx+4]
mov [eax+4], edx
mov eax, [ebp+AParent]
mov eax, [eax+4]
mov edx, [ebp+Result]
mov [eax], edx
jmp InsertItem_if2end
InsertItem_if2else:
xor edx, edx
mov eax, [ebp+Result]
mov [eax+4], edx
InsertItem_if2end:
mov eax, [ebp+Result]
mov edx, [ebp+AParent]
mov [edx+4], eax
InsertItem_if1end:
mov eax, [ebp+Result]
add esp, 4
pop ebp
ret
endp
proc ClearItems
j = -8
i = -4
AFirst = 8
push ebp
mov ebp, esp
sub esp, 8
cmp dword [ebp+AFirst], 0 ; if1
jz ClearItems_end
mov eax, [ebp+AFirst]
mov [ebp+i], eax
cmp dword [ebp+i], 0
jz ClearItems_end
ClearItems_loop_start:
mov eax, [ebp+i]
mov eax, [eax+8]
invoke VirtualFree, eax, 0, MEM_RELEASE
mov eax, [ebp+i]
mov eax, [eax+4]
mov [ebp+j], eax
mov eax, [ebp+i]
invoke LocalFree, eax
mov eax, [ebp+j]
mov [ebp+i], eax
cmp dword [ebp+i], 0
jnz ClearItems_loop_start
ClearItems_end:
add esp, 8
pop ebp
ret
endp
proc RemoveByData
i = -8
Result = -4
AFirst = 8
AData = 0Ch
push ebp
mov ebp, esp
sub esp, 8
cmp dword [ebp+AFirst], 0 ; if1
jnz RemoveByData_if1end
xor eax, eax
mov [ebp+Result], eax
jmp RemoveByData_end
RemoveByData_if1end:
mov eax, [ebp+AFirst]
mov [ebp+i], eax
mov eax, [ebp+AFirst]
mov [ebp+Result], eax
cmp dword [ebp+i], 0 ; loop condition
jz RemoveByData_end
RemoveByData_loop:
mov eax, [ebp+i]
mov eax, [eax+8]
cmp eax, [ebp+AData] ; if2
jnz RemoveByData_if2end
mov eax, [ebp+i]
cmp eax, [ebp+AFirst] ; if3
jnz RemoveByData_if3else
mov eax, [ebp+i]
mov eax, [eax+4]
mov [ebp+Result], eax
mov eax, [ebp+Result]
xor edx, edx
mov [eax], edx
jmp RemoveByData_if3end
RemoveByData_if3else:
mov eax, [ebp+i]
cmp dword [eax], 0 ; if4
jz RemoveByData_if4end
mov eax, [ebp+i]
mov eax, [eax]
mov edx, [ebp+i]
mov edx, [edx+4]
mov [eax+4], edx
RemoveByData_if4end:
mov eax, [ebp+i]
cmp dword [eax+4], 0 ; if5
jz RemoveByData_if3end
mov eax, [ebp+i]
mov eax, [eax+4]
mov edx, [ebp+i]
mov edx, [edx]
mov [eax], edx
RemoveByData_if3end:
mov eax, [ebp+i]
mov eax, [eax+8]
invoke VirtualFree, eax, 0, MEM_RELEASE
mov eax, [ebp+i]
invoke LocalFree, eax
jmp RemoveByData_end
RemoveByData_if2end:
mov eax, [ebp+i]
mov eax, [eax+4]
mov [ebp+i], eax
cmp dword [ebp+i], 0
jnz RemoveByData_loop
RemoveByData_end:
mov eax, [ebp+Result]
add esp, 8
pop ebp
ret
endp
start:
invoke VirtualAlloc, NULL, 1024*1024*10, MEM_COMMIT, PAGE_READONLY
mov [aaa1], eax
invoke VirtualAlloc, NULL, 1024*1024*10, MEM_COMMIT, PAGE_READONLY
mov [bbb1], eax
invoke VirtualAlloc, NULL, 1024*1024*10, MEM_COMMIT, PAGE_READONLY
mov [ccc1], eax
push [ccc1]
push NULL
call InsertItem
add esp, 8
mov [root], eax
push [bbb1]
push [root]
call InsertItem
add esp, 8
push [aaa1]
push eax
call InsertItem
add esp, 8
push [bbb1]
push [root]
call RemoveByData
add esp, 8
mov [root], eax
push [root]
call ClearItems
add esp, 4
invoke ExitProcess, 0
section '.data' readable writeable
root dd ?
aaa1 dd ?
bbb1 dd ?
ccc1 dd ?
section '.idata' import data readable
library kernel, 'KERNEL32.DLL'
import kernel,\
LocalAlloc, 'LocalAlloc',\
LocalFree, 'LocalFree',\
VirtualAlloc, 'VirtualAlloc',\
VirtualFree, 'VirtualFree',\
ExitProcess , 'ExitProcess'VirtualAlloc/VirtualFree - в качестве примера, ибо в качестве этакого менеджера памяти сделано все это. Смещения в структуре не стал расписывать константами, ибо нафиг не надо, хотя стоило бы. Последний раз редактировалось M.A.D.M.A.N., 17.04.2013 в 11:51. |
|
#4
|
||||
|
||||
|
Че-то много.
У меня было куда меньше. Что-то вродеКод:
; List базируем на esi mov esi,[ListRoot] @@: cmp[List.Next], 0 jz @f mov esi,[List.Next] jmp @b @@: invoke LocalAlloc, ... mov[List.Next], eax mov esi, eax mov[List.Next], 0 ; добавляем данные и выходим Код:
; на этот раз List базируем на eax mov esi,[ListRoot] invoke LocalAlloc, ... mov[ListRoot], eax mov[List.Next], esi ; добавляем данные и выходим Последний раз редактировалось Bargest, 17.04.2013 в 22:07. |
|
#5
|
||||
|
||||
|
Спасибо за замечания.
Да я просто чтоб не заморачиваться - в дельфи написал, потом выдергал код (ХЕ3, обратите внимание на цикл while, как она его забавно скомпилировала). Вот эту вот херь: Код:
//type // // двусвязный список // PMemPtrItem = ^TMemPtrItem; // TMemPtrItem = packed record // Left, // Right: PMemPtrItem; // Data: Pointer; // end; // // // // function InsertItem(const AParent: PMemPtrItem; // const AData: Pointer): PMemPtrItem; cdecl; // begin // Result := PMemPtrItem(LocalAlloc($40, SizeOf(TMemPtrItem))); // Result^.Left := nil; // Result^.Right := nil; // Result^.Data := AData; // // if AParent <> nil then // begin // Result^.Left := AParent; // // if AParent^.Right <> nil then // begin // вставка // Result^.Right := AParent^.Right; // AParent^.Right^.Left := Result; // end else // begin // добавление // Result^.Right := nil; // end; // // AParent^.Right := Result; // end; // end; // // // чистка слева направо // procedure ClearItems(const AFirst: PMemPtrItem); cdecl; // var // i, j: PMemPtrItem; // begin // if AFirst = nil then // Exit; // // i := AFirst; // while i <> nil do // begin // VirtualFree(i^.Data, 0, MEM_RELEASE); // // j := i^.Right; // LocalFree(integer(i)); // i := j; // end; // end; // // // считаем, что данные там уникальные // // тоже слева направо ищем // // ф-я возвращает первую запись из всего списка // function RemoveByData(const AFirst: PMemPtrItem; // const AData: Pointer): PMemPtrItem; cdecl; // var // i: PMemPtrItem; // begin // if AFirst = nil then // Exit(nil); // // i := AFirst; // Result := AFirst; // // while i <> nil do // begin // if i^.Data = AData then // begin // if i = AFirst then // begin // Result := i^.Right; // Result^.Left := nil; // end else // begin // if i^.Left <> nil then // i^.Left^.Right := i^.Right; // // if i^.Right <> nil then // i^.Right^.Left := i^.Left; // end; // // удаляем // VirtualFree(i^.Data, 0, MEM_RELEASE); // LocalFree(integer(i)); // // Exit; // end; // // i := i^.Right; // end; // end; Последний раз редактировалось M.A.D.M.A.N., 18.04.2013 в 08:16. |