Subversion Repositories Kolibri OS

Rev

Rev 919 | Rev 1001 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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