Re: Formatting in assembly




Herbert Kleebauer wrote:
Betov wrote:
"James Daughtry" <mordock32@xxxxxxxxxxx> écrivait

atoi:
mov esi,D$esp+4 | mov ecx,D$esp+8
mov eax,0

L0: jecxz L1>
; Convert from ASCII, add to LSD
movzx ebx,B$esi | sub ebx,'0'
mov edx,10 | mul edx | add eax,ebx

inc esi | dec ecx
jmp L0<
L1:
ret

----------------------------------------------------
Proc AsciiToEax:
Arguments @Buffer, @NumberOfChars
Uses esi, ebx, ecx, edx

mov esi D@Buffer, ecx D@NumberOfChars
mov eax 0, ebx 0, edx 10

While ecx > 0
mul edx
mov bl B$esi | sub bl '0' | add eax ebx
inc esi | dec ecx
End_While
EndP
----------------------------------------------------

You are joking again. That looks like a random distribution of characters
on the screen. And if you read a single line, you have to move your eyes
from left to right to left to right ....

mov bl B$esi | sub bl '0' | add eax ebx
^ ^ ^ ^ ^ ^ ^ ^ ^
1 3 2 4 6 5 7 9 8

I'm not sure I understand why that's any harder to read than the same
thing vertically.

AsciiToEax:
00000000: 3e 8b 74 24 04 move.l 4.b(r7),r5 ; pointer to buffer
00000005: 3e 8b 4c 24 08 move.l 8.b(r7),r2 ; number of digits
0000000a: b8 00000000 move.l #0,r0
0000000f: bb 00000000 move.l #0,r3
00000014: ba 0000000a move.l #10,r1

00000019: 81 f9 00000000 _10: cmp.l #0,r2
0000001f: 76 0d bls.b _20
00000021: f7 e2 mulu.l r1,r0,r1|r0
00000023: 8a 1e move.b (r5),r3
00000025: 80 eb 30 sub.b #'0',r3
00000028: 01 d8 add.l r3,r0
0000002a: 46 inc.l r5
0000002b: 49 dec.l r2
0000002c: eb eb br.b _10
0000002e: c3 _20: rts.l

Some comments:

If the number of digits is 0, you don't need to initializes r5,r3,r1

Good point. So it makes sense to initialize r2 and jump to the end if
the value is 0?

"eor.l r0,r0" is 3 bytes shorter than a "move.l #0,r0"

Is this true on the x86? It looks like you're using 68000 instructions,
so the benefit might not exist on a different processor.

"lea.l 10.b(r0),r1" is two bytes shorter than a "move.l #10,r1"

How about just using imul instead of mul. Then I can use an immediate
instead of playing with the awkward register dance of mul and the issue
goes away. :-)

If the number doesn't fit into 32 bit, then your "10" in edx
is destroyed by the multiplication, better us a different register.

That's why I had it in the loop. I'm not sure why Betov changed that.

You have two branch instruction within the loop, only one is needed.

If r2 is guaranteed to be greater than 0, you can get away with only
one. I didn't catch that, so ended up using two. I guess I'm still not
quite thinking in assembly yet. :-)

Here an "assembler version" of the code:


0000002f: 31 c0 atoi: eor.l r0,r0
00000031: 3e 8b 4c 24 08 move.l 8.b(r7),r2 ; number of digits
00000036: 09 c9 or.l r2,r2
00000038: 74 15 beq.b _20
0000003a: 3e 8b 74 24 04 move.l 4.b(r7),r5 ; pointer to buffer
0000003f: 31 db eor.l r3,r3

00000041: 6b c0 0a _10: mulsq.l #10,r0,r0
00000044: 8a 1e move.b (r5),r3
00000046: 80 eb 30 sub.b #'0',r3
00000049: 01 d8 add.l r3,r0
0000004b: 46 inc.l r5
0000004c: 49 dec.l r2
0000004d: 75 f2 bne.b _10
0000004f: c3 _20: rts.l

How about this, better?

jrd_atoi:
xor eax,eax
mov ecx,D§esp+8 | jecxz L1>
mov esi,D§esp+4

; Convert from ASCII, add to LSD
L0: movzx ebx,B§esi | sub ebx,'0'
imul eax,10 | add eax,ebx

inc esi | dec ecx
jnz L0<
L1:
ret

Aside from posting code that I have trouble understanding without a
68000 reference handy, good stuff! Thanks :-)

.



Relevant Pages