Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ;MM_ = MemoryManager
  2. ;Этот модуль позволяет выделять память маленькими кусочками, оптимально используя
  3. ;страницы памяти
  4. ;Блоки - это одна или несколько страниц, которые имеют запись
  5. ;в MM_BlockInfo и которые в конце имеют стекообразную структуру(в смысле
  6. ;растёт к меньшим адресам), заканчивающейся dword 0. В начале блока
  7. ;находятся данные. В структуре находятся пары dword'ов: начало
  8. ;участков, их конец(посл. байт+1). Эти пары всегда сортируются по
  9. ;расположению описываемых
  10. ;участков в обратном порядке, т.е. в самом конце блока будет пара данных
  11. ;на самый первый участок. Для выделения памяти нужно найти блок, в котором
  12. ;достаточно места (причём необходимое место = запрашиваемый объём + место
  13. ;под пару с данными в конце блока) и вставить пару с нужными данными.
  14. ;Для удаления участка нужно только убрать из пар пару с нужным участком
  15. ;и поправить расположение остальных пар.
  16. ;begData1.....endData1,begData2...endData2,.......0,beg2,end2,beg1,end1
  17.  
  18.  
  19. ;выделяет память
  20. ;return eax = указатель на выделеный блок
  21. ;proc MM_AllocMem stdcall,Size:DWORD
  22.  
  23. ;БАГ в выделении крупных кусков: всегда выделяет новую страницу
  24.  
  25.  
  26.  
  27. align 4
  28. MM_AllocMem:
  29.         Size equ ebp+8
  30.         begFree equ ebp-8 ;начало
  31.         endFree equ ebp-4 ;и конец свободного места от конца инфы до
  32.         endArea equ ebp-12
  33.         push    ebp
  34.         mov     ebp,esp
  35.         add     esp,-4*3
  36.         push    ebx edi esi
  37. ;dps 'MEM: '
  38. ;dph [Size]
  39. ;dps ' '
  40.                                 ;начала пар записей
  41.         mov     edx,[MM_NBlocks]
  42.         cmp     edx,0
  43.         jne     .BegTestBlocks         ;если блоков нет, то добавить новый
  44.         mov     ecx,[Size]
  45.         call    AddBlock
  46.         jmp     .return
  47. align 4
  48.  .BegTestBlocks:
  49.  
  50.  
  51.         xor     ebx,ebx
  52.         mov     ecx,edx
  53. align 4
  54.   .TestBlock:    ;проверка блока
  55.                    ;проверка: есть ли место для ещё одной пары
  56.         mov     edi,[MM_BlocksInfo+ebx]
  57.         add     edi,[MM_BlocksInfo+ebx+4]
  58.         mov     [endArea], edi
  59.         sub     edi,4
  60.  
  61.         cmp     dword[edi],0     ;если в блоке нет ни одной записи
  62.         jne     .NoEmptyBlock
  63.         mov     eax,[MM_BlocksInfo+ebx]
  64.         mov     dword[edi-4],eax
  65.         mov     dword[edi],eax
  66.         mov     edx,[Size]
  67.         add     dword[edi],edx
  68.         mov     dword[edi-8],0
  69.         jmp     .return
  70. align 4
  71.  .NoEmptyBlock:
  72.         xor     eax,eax
  73.         push    ecx
  74.         or      ecx,-1
  75.         std
  76.         repne   scasd
  77.         cld
  78.         pop     ecx
  79.         mov     eax,[edi+12] ;конец посл участка
  80.         add     eax,4
  81.         cmp     eax,edi
  82.         jb      @f
  83.  
  84.         add     ebx,8
  85.         dec     ecx
  86.         jnz     .TestBlock
  87.  
  88.         mov     ecx,[Size]
  89.         call    AddBlock
  90.         jmp     .return
  91.      @@:
  92.  
  93.  
  94.         mov     [begFree],eax  ;eax = конец посл. участка + 4
  95.         mov     [endFree],edi  ;edi = указатель на конец посл участка - 12
  96.         sub     dword[begFree],4
  97.         add     dword[endFree],12
  98.  
  99.    ;проверка перед всеми участками
  100.         mov     edi,[MM_BlocksInfo+ebx]
  101.         mov     eax,[endArea]
  102.         mov     eax,[eax-8]
  103.         sub     eax,[MM_BlocksInfo+ebx]
  104.         cmp     eax,[Size]
  105.         ja      .AddInBegBlock
  106.  
  107.    ;проверка между участками
  108.         mov     eax,[endArea]
  109.         cmp     dword[eax-12],0
  110.         je      .EndTest ;если в блоке только 1 участок
  111.  
  112.         sub     eax,4
  113.      @@:
  114.         mov     edi,[eax-12]
  115.         sub     edi,[eax]
  116.         cmp     edi,[Size]
  117.         jae     .AddInMiddle
  118.         sub     eax,8
  119.         cmp     dword[eax-8],0
  120.         jne     @b
  121.  
  122.    .EndTest:
  123.  
  124.    ;проверка после всех блоков
  125.         mov     eax,[begFree]
  126.         mov     edi,[endFree]
  127.         lea     esi,[edi-8]    ;8 - место под запись
  128.         sub     esi,eax
  129.  
  130.         cmp     esi,[Size]
  131.         ja      .AddInEnd
  132.  
  133.         add     ebx,8
  134.         dec     ecx
  135.         jnz     .TestBlock
  136.  
  137.         mov     ecx,[Size]
  138.         call    AddBlock
  139.  
  140.         jmp     .return
  141. align 4
  142.   .AddInBegBlock: ;Добавить в начало. В edi начало блока
  143.         ;pop     eax
  144.  
  145.         mov     eax,edi
  146.         add     eax,[MM_BlocksInfo+ebx+4]
  147.         sub     eax,4
  148.         push    eax
  149.         call    MoveRecordsLeft
  150.         pop     eax
  151.         mov     [eax-4],edi
  152.         push    edi
  153.         add     edi,[Size]
  154.         mov     [eax],edi
  155.         pop     eax
  156.  
  157.         jmp     .return
  158. align 4
  159.   .AddInMiddle:  ;Добавить между участками, еах=конец участка перед свободным местом
  160.  
  161.         ;pop     ecx   ;add     esp,4
  162.         push    eax
  163.         sub     eax,8
  164.         call    MoveRecordsLeft
  165.         pop     eax
  166.  
  167.         mov     edx,[eax]
  168.         mov     [eax-12],edx
  169.         add     edx,[Size]
  170.         mov     [eax-8],edx
  171.         mov     eax,[eax]
  172.         jmp     .return
  173. align 4
  174.   .AddInEnd:  ;Добавить после участков. еdi=указатель на 2ой элем пары с инфой о посл участке
  175.  
  176.         ;add     esp,4
  177.         mov     eax,[edi]
  178.         mov     [edi-12],eax
  179.         push    eax
  180.         add     eax,[Size]
  181.         mov     [edi-8],eax
  182.         pop     eax
  183.  
  184. .return:
  185.  
  186.         pop     esi edi ebx
  187.         leave
  188.         ret 4
  189.  
  190. restore Xren
  191. restore Size
  192. restore begFree
  193. restore endFree
  194.  
  195.  
  196.  
  197. ;eax - первый сдвигаемый dword
  198. ;сдвигает пары dword'ов на 8B назад включая dword 0
  199. align 4
  200. proc MoveRecordsLeft
  201. local   var1:DWORD,\
  202.         var2:DWORD
  203.  
  204.         p2p     [var1],[eax]
  205.         p2p     [var2],[eax-4]
  206.  
  207.      @@:
  208.         sub     eax,8
  209.         cmp     dword[var1],0
  210.         je      @f
  211.  
  212.         push    dword[eax]
  213.         p2p     [eax],[var1]
  214.         pop     dword[var1]
  215.  
  216.         push    dword[eax-4]
  217.         p2p     [eax-4],[var2]
  218.         pop     dword[var2]
  219.         jmp     @b
  220.       @@:
  221.  
  222.         mov     dword[eax],0
  223.         ret
  224. endp
  225.  
  226. ;ecx = размер требуемого участка
  227. ;добавляет блок и создаёт в нём участок размером ecx
  228. align 4
  229. proc AddBlock
  230.         mov     edx,[MM_NBlocks]
  231.         inc     edx
  232.         cmp     edx,MM_MAX_BLOCKS
  233.         ja      .ErrAlloc
  234.  
  235.         push    ecx
  236.         add     ecx,12
  237.  
  238.         test    ecx,0FFFh          ;округляем до большей границы страницы
  239.         jz      @f
  240.         add     ecx,1000h
  241.         and     ecx,0FFFFF000h
  242.       @@:
  243.  
  244.         mcall   68,12,ecx
  245.         mov     [MM_NBlocks],edx     ;заполнение данных о блоке
  246.         mov     [edx*4*2-4*2+MM_BlocksInfo],eax  ;begin
  247.         mov     [edx*4*2-4+MM_BlocksInfo],ecx    ;size
  248. ;dps 'Block '
  249. ;dph eax
  250. ;dps ' '
  251. ;dph ecx
  252. ;dnl
  253.         mov     edx,eax
  254.         add     edx,ecx
  255.         mov     [edx-8],eax
  256.         pop     dword[edx-4]
  257.         add     [edx-4],eax
  258.         mov     dword[edx-12],0
  259.         ret
  260.  
  261.  .ErrAlloc:
  262.         pop     ecx
  263.         xor     eax,eax
  264.         ret
  265. endp
  266. ;-------------------------------------------------------------------------------
  267.  
  268.  
  269. ;удаляет  память
  270. ;proc MM_DelMem Pointer:DWORD
  271. align 4
  272. MM_DelMem:
  273.         Pointer equ ebp+8
  274.         push    ebp
  275.         mov     ebp,esp
  276. ; int3
  277.         push    ebx
  278.         mov     ecx,[MM_NBlocks]
  279.         test    ecx,ecx
  280.         jnz     @f
  281.         xor     eax,eax
  282.         pop     ebx
  283.         leave
  284.         ret 4
  285.       @@:
  286.  
  287.         mov     eax,[Pointer]
  288.         xor     ebx,ebx ;ebx - (номер блока)*8
  289.    .TestBlocks:
  290.         mov     edx,[MM_BlocksInfo+ebx]
  291.         add     edx,[MM_BlocksInfo+ebx+4]
  292.         sub     edx,8         ;edx - указатель на 1ую пару
  293.  
  294.      .TestMems:
  295.         cmp     [edx],eax
  296.         je      .FoundMem
  297.  
  298.         sub     edx,8
  299.         cmp     dword[edx+4],0
  300.         jne     .TestMems
  301.  
  302.         add     ebx,4
  303.         loop    .TestBlocks
  304.  
  305.         xor     eax,eax
  306.         pop     ebx
  307.         leave
  308.         ret 4
  309.  
  310.    .FoundMem:
  311.         cmp     dword[edx-4],0
  312.         jz      .EndDelMem
  313.  
  314.    .NextMoveMem:
  315.         p2p    [edx+4],[edx-4]
  316.         p2p    [edx],[edx-8]
  317.         sub     edx,8
  318.         cmp     dword[edx-4],0
  319.         jnz     .NextMoveMem
  320.  
  321.     .EndDelMem:
  322.         mov     dword[edx+4],0
  323.         mov     dword[edx],0
  324.  
  325.         mov     eax,1
  326.         pop     ebx
  327.         leave
  328.         ret 4
  329.  
  330. restore Pointer
  331.