Subversion Repositories Kolibri OS

Rev

Rev 1001 | Rev 1295 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;================================================================================================;;
  2. ;;//// libini_p.asm //// (c) mike.dld, 2006-2008 /////////////////////////////////////////////////;;
  3. ;;================================================================================================;;
  4. ;;                                                                                                ;;
  5. ;; This file is part of Common development libraries (Libs-Dev).                                  ;;
  6. ;;                                                                                                ;;
  7. ;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
  8. ;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
  9. ;; of the License, or (at your option) any later version.                                         ;;
  10. ;;                                                                                                ;;
  11. ;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
  12. ;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
  13. ;; Lesser General Public License for more details.                                                ;;
  14. ;;                                                                                                ;;
  15. ;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev.  ;;
  16. ;; If not, see <http://www.gnu.org/licenses/>.                                                    ;;
  17. ;;                                                                                                ;;
  18. ;;================================================================================================;;
  19.  
  20. mem.alloc   dd ?
  21. mem.free    dd ?
  22. mem.realloc dd ?
  23. dll.load    dd ?
  24.  
  25. ;;================================================================================================;;
  26. proc libini._.init ;//////////////////////////////////////////////////////////////////////////////;;
  27. ;;------------------------------------------------------------------------------------------------;;
  28. ;? Library entry point (called after library load)                                                ;;
  29. ;;------------------------------------------------------------------------------------------------;;
  30. ;> eax = memory allocation routine <mem.alloc*>                                                   ;;
  31. ;> ebx = memory freeing routine <mem.free*>                                                       ;;
  32. ;> ecx = memory reallocation routine <mem.realloc*>                                               ;;
  33. ;> edx = library loading routine <dll.load*>                                                      ;;
  34. ;;------------------------------------------------------------------------------------------------;;
  35. ;< eax = 1 (fail) / 0 (ok) (library initialization result)                                        ;;
  36. ;;================================================================================================;;
  37.         mov     [mem.alloc], eax
  38.         mov     [mem.free], ebx
  39.         mov     [mem.realloc], ecx
  40.         mov     [dll.load], edx
  41.  
  42.         invoke  dll.load, @IMPORT
  43.         or      eax, eax
  44.         jz      .ok
  45.  
  46.         xor     eax, eax
  47.         inc     eax
  48.         ret
  49.  
  50.   .ok:  xor     eax,eax
  51.         ret
  52. endp
  53.  
  54. ;;================================================================================================;;
  55. proc libini._.unget_char _f ;/////////////////////////////////////////////////////////////////////;;
  56. ;;------------------------------------------------------------------------------------------------;;
  57. ;? --- TBD ---                                                                                    ;;
  58. ;;------------------------------------------------------------------------------------------------;;
  59. ;> --- TBD ---                                                                                    ;;
  60. ;;------------------------------------------------------------------------------------------------;;
  61. ;< --- TBD ---                                                                                    ;;
  62. ;;================================================================================================;;
  63.         push    eax ecx
  64.         mov     ecx, [_f]
  65.         inc     [ecx + IniFile.cnt]
  66.         dec     esi
  67.         mov     eax, [ecx + IniFile.bsize]
  68.         cmp     [ecx + IniFile.cnt], eax
  69.         jle     @f
  70.         stdcall libini._.unload_block, [_f]
  71.     @@: pop     ecx eax
  72.         ret
  73. endp
  74.  
  75. ;;================================================================================================;;
  76. proc libini._.get_char _f ;///////////////////////////////////////////////////////////////////////;;
  77. ;;------------------------------------------------------------------------------------------------;;
  78. ;? --- TBD ---                                                                                    ;;
  79. ;;------------------------------------------------------------------------------------------------;;
  80. ;> --- TBD ---                                                                                    ;;
  81. ;;------------------------------------------------------------------------------------------------;;
  82. ;< --- TBD ---                                                                                    ;;
  83. ;;================================================================================================;;
  84.         mov     ecx, [_f]
  85.         dec     [ecx + IniFile.cnt]
  86.         jns     @f
  87.         stdcall libini._.preload_block, [_f]
  88.         dec     [ecx + IniFile.cnt]
  89.     @@: lodsb
  90.         ret
  91. endp
  92.  
  93. ;;================================================================================================;;
  94. proc libini._.skip_nonblanks _f ;/////////////////////////////////////////////////////////////////;;
  95. ;;------------------------------------------------------------------------------------------------;;
  96. ;? --- TBD ---                                                                                    ;;
  97. ;;------------------------------------------------------------------------------------------------;;
  98. ;> --- TBD ---                                                                                    ;;
  99. ;;------------------------------------------------------------------------------------------------;;
  100. ;< --- TBD ---                                                                                    ;;
  101. ;;================================================================================================;;
  102.         mov     ecx, [_f]
  103.     @@: stdcall libini._.get_char, [_f]
  104.         cmp     al, 32
  105.         je      @b
  106.         cmp     al, 13
  107.         je      @b
  108.         cmp     al, 10
  109.         je      @b
  110.         cmp     al, 9
  111.         je      @b
  112.         cmp     al, ini.COMMENT_CHAR
  113.         jne     @f
  114.         stdcall libini._.skip_line, [_f]
  115.         jmp     @b
  116.     @@: stdcall libini._.unget_char, [_f]
  117.         ret
  118. endp
  119.  
  120. ;;================================================================================================;;
  121. proc libini._.skip_spaces _f ;////////////////////////////////////////////////////////////////////;;
  122. ;;------------------------------------------------------------------------------------------------;;
  123. ;? --- TBD ---                                                                                    ;;
  124. ;;------------------------------------------------------------------------------------------------;;
  125. ;> --- TBD ---                                                                                    ;;
  126. ;;------------------------------------------------------------------------------------------------;;
  127. ;< --- TBD ---                                                                                    ;;
  128. ;;================================================================================================;;
  129.         mov     ecx, [_f]
  130.     @@: stdcall libini._.get_char, [_f]
  131.         cmp     al, 32
  132.         je      @b
  133.         cmp     al, 9
  134.         je      @b
  135.     @@: stdcall libini._.unget_char, [_f]
  136.         ret
  137. endp
  138.  
  139. ;;================================================================================================;;
  140. proc libini._.skip_line _f ;//////////////////////////////////////////////////////////////////////;;
  141. ;;------------------------------------------------------------------------------------------------;;
  142. ;? --- TBD ---                                                                                    ;;
  143. ;;------------------------------------------------------------------------------------------------;;
  144. ;> --- TBD ---                                                                                    ;;
  145. ;;------------------------------------------------------------------------------------------------;;
  146. ;< --- TBD ---                                                                                    ;;
  147. ;;================================================================================================;;
  148.         mov     ecx, [_f]
  149.     @@: stdcall libini._.get_char, [_f]
  150.         or      al, al
  151.         jz      @f
  152.         cmp     al, 13
  153.         je      @f
  154.         cmp     al, 10
  155.         jne     @b
  156.     @@: stdcall libini._.unget_char, [_f]
  157.         ret
  158. endp
  159.  
  160. ;;================================================================================================;;
  161. proc libini._.unload_block _f ;///////////////////////////////////////////////////////////////////;;
  162. ;;------------------------------------------------------------------------------------------------;;
  163. ;? --- TBD ---                                                                                    ;;
  164. ;;------------------------------------------------------------------------------------------------;;
  165. ;> --- TBD ---                                                                                    ;;
  166. ;;------------------------------------------------------------------------------------------------;;
  167. ;< --- TBD ---                                                                                    ;;
  168. ;;================================================================================================;;
  169.         push    eax ebx ecx
  170.         mov     ebx, [_f]
  171.         mov     eax, [ebx + IniFile.pos]
  172.         add     eax, -ini.BLOCK_SIZE
  173.         invoke  file.seek, [ebx + IniFile.fh], eax, SEEK_SET
  174.         stdcall libini._.preload_block, ebx
  175.         add     esi, eax
  176.         mov     [ebx + IniFile.cnt], 0
  177.         pop     ecx ebx eax
  178.         ret
  179. endp
  180.  
  181. ;;================================================================================================;;
  182. proc libini._.preload_block _f ;//////////////////////////////////////////////////////////////////;;
  183. ;;------------------------------------------------------------------------------------------------;;
  184. ;? --- TBD ---                                                                                    ;;
  185. ;;------------------------------------------------------------------------------------------------;;
  186. ;> --- TBD ---                                                                                    ;;
  187. ;;------------------------------------------------------------------------------------------------;;
  188. ;< --- TBD ---                                                                                    ;;
  189. ;;================================================================================================;;
  190.         push    eax ebx ecx
  191.         mov     ebx, [_f]
  192.     @@: mov     esi, [ebx + IniFile.buf]
  193.         push    edi
  194.         mov     edi, esi
  195.         mov     ecx, ini.BLOCK_SIZE / 4
  196.         xor     eax, eax
  197.         rep     stosd
  198.         pop     edi
  199.         invoke  file.tell, [ebx + IniFile.fh]
  200.         mov     [ebx + IniFile.pos], eax
  201.         invoke  file.read, [ebx + IniFile.fh], esi, ini.BLOCK_SIZE
  202.         mov     esi,[ebx + IniFile.buf]
  203.         cmp     eax,ini.BLOCK_SIZE
  204.         jl      @f
  205.     @@: mov     [ebx + IniFile.cnt], eax
  206.         mov     [ebx + IniFile.bsize], eax
  207.         pop     ecx ebx eax
  208.         ret
  209. endp
  210.  
  211. ;;================================================================================================;;
  212. proc libini._.reload_block _f ;///////////////////////////////////////////////////////////////////;;
  213. ;;------------------------------------------------------------------------------------------------;;
  214. ;? --- TBD ---                                                                                    ;;
  215. ;;------------------------------------------------------------------------------------------------;;
  216. ;> --- TBD ---                                                                                    ;;
  217. ;;------------------------------------------------------------------------------------------------;;
  218. ;< --- TBD ---                                                                                    ;;
  219. ;;================================================================================================;;
  220.         push    eax ebx ecx
  221.         mov     ebx, [_f]
  222.         push    [ebx + IniFile.bsize]
  223.         push    esi [ebx + IniFile.cnt]
  224.         invoke  file.seek, [ebx + IniFile.fh], [ebx + IniFile.pos], SEEK_SET
  225.         stdcall libini._.preload_block, ebx
  226.         pop     [ebx + IniFile.cnt] esi
  227.         pop     eax
  228.         sub     eax,[ebx + IniFile.bsize]
  229.         sub     [ebx + IniFile.cnt], eax
  230.         pop     ecx ebx eax
  231.         ret
  232. endp
  233.  
  234. ; f_info - contains current file block number
  235. ; esi    - position in block from where to shift
  236. ; ecx    - number of bytes to shift by
  237.  
  238. ;;================================================================================================;;
  239. proc libini._.shift_content _f, _delta ;//////////////////////////////////////////////////////////;;
  240. ;;------------------------------------------------------------------------------------------------;;
  241. ;? Shift file content starting from cursor position (~ delete)                                    ;;
  242. ;? Content is copied by 'delta' bytes up/down                                                     ;;
  243. ;;------------------------------------------------------------------------------------------------;;
  244. ;> --- TBD ---                                                                                    ;;
  245. ;;------------------------------------------------------------------------------------------------;;
  246. ;< eax = -1 (fail) / 0 (ok)                                                                       ;;
  247. ;;================================================================================================;;
  248. locals
  249.   buf dd ?
  250. endl
  251.  
  252.         xor     eax, eax
  253.         cmp     [_delta], 0
  254.         je      .skip
  255.  
  256.         push    ebx ecx
  257.         invoke  mem.alloc, ini.BLOCK_SIZE
  258.         or      eax, eax
  259.         jz      .fail
  260.         mov     [buf], eax
  261.  
  262.         cmp     [_delta], 0
  263.         jl      .down
  264.  
  265.         mov     ebx, [_f]
  266.         mov     ecx, [ebx + IniFile.cnt]
  267.         mov     ebx, [ebx + IniFile.fh]
  268.         invoke  file.tell, ebx
  269.         sub     eax, ecx
  270.         invoke  file.seek, ebx, eax, SEEK_SET
  271.     @@: invoke  file.seek, ebx, [_delta], SEEK_CUR
  272.         invoke  file.eof?, ebx
  273.         or      eax, eax
  274.         jnz     .done
  275.         invoke  file.read, ebx, [buf], ini.BLOCK_SIZE
  276.         mov     ecx, eax
  277.         mov     eax, [_delta]
  278.         neg     eax
  279.         sub     eax, ecx
  280.         invoke  file.seek, ebx, eax, SEEK_CUR
  281.         invoke  file.write, ebx, [buf], ecx
  282.         jmp     @b
  283.   .done:
  284.         mov     eax, [_delta]
  285.         neg     eax
  286.         invoke  file.seek, ebx, eax, SEEK_CUR
  287.         invoke  file.seteof, ebx
  288.         stdcall libini._.reload_block, [_f]
  289.         invoke  mem.free, [buf]
  290.         pop     ecx ebx
  291.   .skip:
  292.         ret
  293.   .fail:
  294.         or      eax, -1
  295.         pop     ecx ebx
  296.         ret
  297.  
  298.   .down:
  299.         neg     [_delta]
  300.  
  301.         mov     ebx, [_f]
  302.         mov     ecx, [ebx + IniFile.cnt]
  303.         mov     ebx, [ebx + IniFile.fh]
  304.         invoke  file.tell, ebx
  305.         sub     eax, ecx
  306.         lea     edx, [eax - 1]
  307.         push    edx
  308.     @@: invoke  file.seek, ebx, edx, SEEK_SET
  309.         invoke  file.eof?, ebx
  310.         or      eax, eax
  311.         jnz     @f
  312.         add     edx, ini.BLOCK_SIZE
  313.         jmp     @b
  314.     @@: cmp     edx, [esp]
  315.         je      .skip.2
  316.         add     edx, -ini.BLOCK_SIZE
  317.         cmp     edx, [esp]
  318.         jl      @f
  319.         invoke  file.seek, ebx, edx, SEEK_SET
  320.         invoke  file.read, ebx, [buf], ini.BLOCK_SIZE
  321.         mov     ecx, eax
  322.         mov     eax, [_delta]
  323.         sub     eax, ecx
  324.         invoke  file.seek, ebx, eax, SEEK_CUR
  325.         invoke  file.write, ebx, [buf], ecx
  326.         jmp     @b
  327.     @@:
  328.   .skip.2:
  329.         add     esp, 4
  330.         stdcall libini._.reload_block, [_f]
  331.         invoke  mem.free, [buf]
  332.         pop     ecx ebx
  333.         ret
  334. endp
  335.  
  336. ;;================================================================================================;;
  337. proc libini._.get_value_length _f ;///////////////////////////////////////////////////////////////;;
  338. ;;------------------------------------------------------------------------------------------------;;
  339. ;? --- TBD ---                                                                                    ;;
  340. ;;------------------------------------------------------------------------------------------------;;
  341. ;> --- TBD ---                                                                                    ;;
  342. ;;------------------------------------------------------------------------------------------------;;
  343. ;< --- TBD ---                                                                                    ;;
  344. ;;================================================================================================;;
  345.         push    ebx ecx edx eax
  346.         mov     ebx, [_f]
  347.         invoke  file.tell, [ebx + IniFile.fh]
  348.         push    esi [ebx + IniFile.cnt] [ebx + IniFile.pos]
  349.         sub     eax, [ebx + IniFile.cnt]
  350.         mov     edx, eax
  351.  
  352.         stdcall libini._.skip_line, [_f]
  353.         invoke  file.tell, [ebx + IniFile.fh]
  354.         sub     eax, [ebx + IniFile.cnt]
  355.         sub     eax, edx
  356.         mov     [esp + 4 * 3], eax
  357.  
  358.         pop     eax
  359.         invoke  file.seek, [ebx + IniFile.fh], eax, SEEK_SET
  360.         stdcall libini._.preload_block, [_f]
  361.         pop     [ebx + IniFile.cnt] esi
  362.         pop     eax edx ecx ebx
  363.         ret
  364. endp
  365.  
  366. ;;================================================================================================;;
  367. proc libini._.string_copy ;///////////////////////////////////////////////////////////////////////;;
  368. ;;------------------------------------------------------------------------------------------------;;
  369. ;? --- TBD ---                                                                                    ;;
  370. ;;------------------------------------------------------------------------------------------------;;
  371. ;> --- TBD ---                                                                                    ;;
  372. ;;------------------------------------------------------------------------------------------------;;
  373. ;< --- TBD ---                                                                                    ;;
  374. ;;================================================================================================;;
  375.     @@: lodsb
  376.         or      al, al
  377.         jz      @f
  378.         stosb
  379.         jmp     @b
  380.     @@: ret
  381. endp
  382.  
  383. ;;================================================================================================;;
  384. proc libini._.find_next_section _f ;//////////////////////////////////////////////////////////////;;
  385. ;;------------------------------------------------------------------------------------------------;;
  386. ;? --- TBD ---                                                                                    ;;
  387. ;;------------------------------------------------------------------------------------------------;;
  388. ;> --- TBD ---                                                                                    ;;
  389. ;;------------------------------------------------------------------------------------------------;;
  390. ;< --- TBD ---                                                                                    ;;
  391. ;;================================================================================================;;
  392.         push    ebx edi
  393.  
  394.     @@: stdcall libini._.skip_nonblanks, [_f]
  395.         cmp     al, '['
  396.         je      @f
  397.         or      al, al
  398.         jz      .exit_error
  399.         stdcall libini._.skip_line, [_f]
  400.         or      al, al
  401.         jz      .exit_error
  402.         jmp     @b
  403.     @@:
  404.         pop     edi ebx
  405.         xor     eax, eax
  406.         ret
  407.  
  408.   .exit_error:
  409.         pop     edi ebx
  410.         or      eax, -1
  411.         ret
  412. endp
  413.  
  414. ;;================================================================================================;;
  415. proc libini._.find_section _f, _sec_name ;////////////////////////////////////////////////////////;;
  416. ;;------------------------------------------------------------------------------------------------;;
  417. ;? Find section in file                                                                           ;;
  418. ;? Search is performed from the beginning of file                                                 ;;
  419. ;;------------------------------------------------------------------------------------------------;;
  420. ;> --- TBD ---                                                                                    ;;
  421. ;;------------------------------------------------------------------------------------------------;;
  422. ;< eax = -1 (fail) / 0 (ok)                                                                       ;;
  423. ;< [_f.pos] = new cursor position (right after ']' char if eax = 0, at the end of file otherwise) ;;
  424. ;;================================================================================================;;
  425.         push    ebx edi
  426.  
  427.         mov     ecx, [_f]
  428.         invoke  file.seek, [ecx + IniFile.fh], 0, SEEK_SET
  429.         stdcall libini._.preload_block, [_f]
  430.  
  431.   .next_section:
  432.         stdcall libini._.find_next_section, [_f]
  433.         or      eax, eax
  434.         jnz     .exit_error
  435.  
  436.         stdcall libini._.get_char, [_f]
  437.         stdcall libini._.skip_spaces, [_f]
  438.         mov     edi, [_sec_name]
  439.     @@: stdcall libini._.get_char, [_f]
  440.         cmp     al, ']'
  441.         je      @f
  442.         or      al, al
  443.         jz      .exit_error
  444.         cmp     al, 13
  445.         je      .next_section
  446.         cmp     al, 10
  447.         je      .next_section
  448.         scasb
  449.         je      @b
  450.         cmp     byte[edi - 1], 0
  451.         jne     .next_section
  452.         dec     edi
  453.         stdcall libini._.unget_char, [_f]
  454.         stdcall libini._.skip_spaces, [_f]
  455.         stdcall libini._.get_char, [_f]
  456.         cmp     al, ']'
  457.         jne     .next_section
  458.     @@:
  459.         cmp     byte[edi], 0
  460.         jne     .next_section
  461.         pop     edi ebx
  462.         xor     eax, eax
  463.         ret
  464.  
  465.   .exit_error:
  466.         pop     edi ebx
  467.         or      eax, -1
  468.         ret
  469. endp
  470.  
  471. ;;================================================================================================;;
  472. proc libini._.find_key _f, _key_name ;////////////////////////////////////////////////////////////;;
  473. ;;------------------------------------------------------------------------------------------------;;
  474. ;? Find key in section                                                                            ;;
  475. ;? Search is performed within current section starting from cursor position                       ;;
  476. ;;------------------------------------------------------------------------------------------------;;
  477. ;> --- TBD ---                                                                                    ;;
  478. ;;------------------------------------------------------------------------------------------------;;
  479. ;< eax = -1 (fail) / 0 (ok)                                                                       ;;
  480. ;< [_f.pos] = new cursor position (right after '=' char if eax = 0, at the end of file or right   ;;
  481. ;<            before '[' char otherwise)                                                          ;;
  482. ;;================================================================================================;;
  483.         push    ebx edi
  484.  
  485.   .next_value:
  486.         mov     edi, [_key_name]
  487.         stdcall libini._.skip_line, [_f]
  488.         stdcall libini._.skip_nonblanks, [_f]
  489.         or      al, al
  490.         jz      .exit_error
  491.         cmp     al, '['
  492.         je      .exit_error
  493.     @@: stdcall libini._.get_char, [_f]
  494.         or      al, al
  495.         jz      .exit_error
  496.         cmp     al, '='
  497.         je      @f
  498.         scasb
  499.         je      @b
  500.         cmp     byte[edi - 1], 0
  501.         jne     .next_value
  502.         dec     edi
  503.         stdcall libini._.unget_char, [_f]
  504.         stdcall libini._.skip_spaces, [_f]
  505.         stdcall libini._.get_char, [_f]
  506.         cmp     al, '='
  507.         je      @f
  508.         jmp     .next_value
  509.     @@:
  510.         cmp     byte[edi], 0
  511.         jne     .next_value
  512.  
  513.         pop     edi ebx
  514.         xor     eax, eax
  515.         ret
  516.  
  517.   .exit_error:
  518.         pop     edi ebx
  519.         or      eax, -1
  520.         ret
  521. endp
  522.  
  523. ;;================================================================================================;;
  524. proc libini._.low.read_value _f_addr, _buffer, _buf_len ;/////////////////////////////////////////;;
  525. ;;------------------------------------------------------------------------------------------------;;
  526. ;? --- TBD ---                                                                                    ;;
  527. ;;------------------------------------------------------------------------------------------------;;
  528. ;> --- TBD ---                                                                                    ;;
  529. ;;------------------------------------------------------------------------------------------------;;
  530. ;< --- TBD ---                                                                                    ;;
  531. ;;================================================================================================;;
  532.         push    edi eax
  533.         mov     edi, [_buffer]
  534.         stdcall libini._.skip_spaces, [_f_addr]
  535.     @@: dec     [_buf_len]
  536.         jz      @f
  537.         stdcall libini._.get_char, [_f_addr]
  538.         cmp     al, 13
  539.         je      @f
  540.         cmp     al, 10
  541.         je      @f
  542.         stosb
  543.         or      al, al
  544.         jnz     @b
  545.     @@: stdcall libini._.unget_char, [_f_addr]
  546.         mov     byte[edi], 0
  547.         dec     edi
  548.     @@: cmp     edi, [_buffer]
  549.         jb      @f
  550.         cmp     byte[edi], 32
  551.         ja      @f
  552.         mov     byte[edi], 0
  553.         dec     edi
  554.         jmp     @b
  555.     @@: pop     eax edi
  556.         ret
  557. endp
  558.  
  559. ;;================================================================================================;;
  560. proc libini._.str_to_int ;////////////////////////////////////////////////////////////////////////;;
  561. ;;------------------------------------------------------------------------------------------------;;
  562. ;? --- TBD ---                                                                                    ;;
  563. ;;------------------------------------------------------------------------------------------------;;
  564. ;> esi = string buffer address                                                                    ;;
  565. ;;------------------------------------------------------------------------------------------------;;
  566. ;< eax = binary number representation (no overflow checks made)                                   ;;
  567. ;;================================================================================================;;
  568.         push    edx
  569.  
  570.         xor     eax, eax
  571.         xor     edx, edx
  572.  
  573.     @@: lodsb
  574.         cmp     al, '0'
  575.         jb      @f
  576.         cmp     al, '9'
  577.         ja      @f
  578.         add     eax, -'0'
  579.         imul    edx, 10
  580.         add     edx, eax
  581.         jmp     @b
  582.  
  583.     @@: dec     esi
  584.         mov     eax, edx
  585.         pop     edx
  586.         ret
  587. endp
  588.  
  589. ;;================================================================================================;;
  590. proc libini._.int_to_str ;////////////////////////////////////////////////////////////////////////;;
  591. ;;------------------------------------------------------------------------------------------------;;
  592. ;? --- TBD ---                                                                                    ;;
  593. ;;------------------------------------------------------------------------------------------------;;
  594. ;> eax = number to convert                                                                        ;;
  595. ;> ecx = base                                                                                     ;;
  596. ;> edi = string buffer address                                                                    ;;
  597. ;;------------------------------------------------------------------------------------------------;;
  598. ;< --- TBD ---                                                                                    ;;
  599. ;;================================================================================================;;
  600.         push    ecx edx
  601.  
  602.         or      eax, eax
  603.         jns     @f
  604.         mov     byte[edi], '-'
  605.         inc     edi
  606.     @@: call    .recurse
  607.         pop     edx ecx
  608.         ret
  609.  
  610.   .recurse:
  611.         cmp     eax,ecx
  612.         jb      @f
  613.         xor     edx,edx
  614.         div     ecx
  615.         push    edx
  616.         call    .recurse
  617.         pop     eax
  618.     @@: cmp     al,10
  619.         sbb     al,0x69
  620.         das
  621.         stosb
  622.         retn
  623. endp
  624.