Hi,
I'm very new to this and after reading a few tutorials (thanks a lot for the exagone-tuts!) I now wanted to get a little practical.
So this is the first task I gave me. Writing an UrlDecode-DLL.
It took me a while but now it works :)!
But to me it looks very unstructured.
As you may see, I know very little opcodes and know very little about them. I'd really like to get to know better Assembler than that. Please teach me how to!
There are a few question:

    [*]Is there an easyer way to convert 2 HexCars to a number?
    [*]Does that "cld" have any relevance in this context?
    [*]Is there a good way to take advantage of the "rep" command
    [*]I feel very limited with creating a string of fixed length; Is there any other way but using the SysAllocStringByteLen?


    
    
    UrlDecode proc uses ecx , text:DWORD
    LOCAL ReturnString$ :DWORD
    LOCAL ln :DWORD
    LOCAL Occurencys :DWORD

    push esi ;save esi and edi
    push edi

    mov ecx, text
    xor eax, eax

    StartLengthLoop:
    mov dl, [ecx]
    inc ecx ;GetStringLength
    cmp dl, "%"
    jne CharNotFound
    inc eax ;Count Occurency of "%"
    CharNotFound:
    cmp dl, 0
    jne StartLengthLoop

    mov Occurencys, eax ;save "%"-Count as Occurencys
    sub ecx, text ;correct StringLength
    dec ecx
    shl eax, 1 ;calculate NewStringLength
    sub ecx, eax

    jns DontZeroEcx ;end if negative
    mov ecx, 0
    DontZeroEcx:

    mov ln, ecx
    invoke SysAllocStringByteLen,0,ln ;Allocate Space for the resultString
    mov ReturnString$, eax

    cmp ln, 0 ;End if Length is 0
    je TheEnd

    mov esi, text ;Set Pointers to StringVars
    mov edi, ReturnString$
    mov ecx, ln ;zero ecx to use as counter
    cld

    add ln, edi
    cmp Occurencys, 0 ;Check whether there need to be made any replacements
    je NoHex

    StartLoop: ;Start of the ReplacmentLoop
    mov al, [esi] ;copy current char
    cmp al, "%" ;compare to "%"
    jne CharNotFound2

    xor eax, eax
    inc esi
    mov al, [esi] ;GetFirst HexChar

    cmp al, 48 ;Starting the HexConversion
    jl NoValidHex
    cmp al, 57
    jg HexChar
    sub al, 48
    jmp NextChar
    HexChar:
    cmp al, 65
    jl NoValidHex
    cmp al, 70
    jg SmallHex
    sub al, 55
    jmp NextChar
    SmallHex:
    cmp al, 97
    jl NoValidHex
    cmp al, 102
    jg NoValidHex
    sub al, 87
    NextChar:
    inc esi
    mov ah, [esi] ;Proceed with the next char

    cmp ah, 48
    jl NoValidHex2
    cmp ah, 57
    jg HexChar2
    sub ah, 48
    jmp EndHex
    HexChar2:
    cmp ah, 65
    jl NoValidHex2
    cmp ah, 70
    jg SmallHex2
    sub ah, 55
    jmp EndHex
    SmallHex2:
    cmp ah, 97
    jl NoValidHex2
    cmp ah, 102
    jg NoValidHex2
    sub ah, 87
    EndHex:
    shl al, 4 ;Put Results in the correct position
    add al, ah
    mov [edi], al ;save
    jmp EndLoop
    NoValidHex: ;Char was no valid HexChar
    inc esi ;Correct the stringPointerPosition for correct StringLength
    NoValidHex2:
    mov al, "%" ;Just save an "%" if HexChars weren't valid
    mov [edi], al
    jmp EndLoop
    CharNotFound2:
    cmp al, "+" ;if regular Char
    je ReplacePlus
    mov [edi], al
    jmp EndLoop
    ReplacePlus: ;replace "+" with space
    mov al, 32
    mov [edi], al
    EndLoop:
    inc esi ;StringPointer erh?hen
    inc edi
    cmp ln, edi ;end if OutputStringLength reached
    jg StartLoop
    jmp TheEnd
    NoHex: ;No "%" replaceing necessary
    ;rep movsb
    mov al, [esi]
    cmp al, "+" ;Replacing of "+"s only
    je ReplacePlus2
    mov [edi], al
    jmp NoPlus
    ReplacePlus2:
    mov al, 32
    mov [edi], al
    NoPlus:
    inc esi
    inc edi
    cmp ln, edi
    jg NoHex
    jmp TheEnd
    TheEnd:
    mov al, 0 ;terminate String
    mov [edi], al

    mov eax, ReturnString$ ;return String

    pop edi
    pop esi
    ret
    UrlDecode endp
Posted on 2001-09-04 03:44:54 by Butch77
I replaced the HexConversion with this:



xor eax, eax
inc esi
mov ax, [esi] ;Get the 2 HexChars

mov dx, ax ;Convert To Hex
and dx, 16448 ;01000000 01000000
shr dx, 3
add ax, dx
shr dx, 3
add ax, dx
and eax, 3855 ;00001111 00001111
shl al, 4
add al, ah

mov [edi], al
inc esi
jmp EndLoop


I thought this would make it much faster. But it doesn't!
It just differs by 1%...
What takes the whole time?
I really need some good advices.

Thanks
Posted on 2001-09-04 10:26:37 by Butch77
Dang, I wish I could help you dude, but I have no idea how to do what you are doing.
Posted on 2001-09-06 15:18:39 by Kenny
Is there an easyer way to convert 2 HexCars to a number?


; assumptions: esi == addr to source info
; assumptions: edi == addr to dest buffer.
xor eax, eax
xor ebx, ebx ; used as a flag.. for leading zero's
xor edx, edx
mov ax, [esi]
mov cx, 10000
@@:
div cx ; dx < 10000, 1000, 100 etc. etc.
; ax == n in the set {0-6}
; ax == n in the set {0-9} for all else (all other iterations)

.if( bx == 0)&&(ax != 0) ; leading 0's removal..
mov ebx, 1
.endif

.if( bx==1 )
and ax, 30h ; make it an ascii #
mov [edi], ax ; save it
inc edi
.endif

push edx ; save the remainder..

mov ax, dx ; divide the divisor by 10.. ie do 1000's, 100's etc.
xor edx, edx
mov cx, 10
div cx ; ax = cx / 10
mov ecx, eax ; update the divisor

xor edx, edx ; prepare for next loop
pop eax ; set the remainder to be divided..

cmp ecx, 0 ; see if were done... ( ie) last div/10 was a fraction )
jne @B


Didnt test this, but it should work...

Does that "cld" have any relevance in this context?

None that i can tell.. expecially since you commented out the "rep movsb" command..


Is there a good way to take advantage of the "rep" command

Yes, expecially if you study the MemCopy fucntion in the MASM32Lib...


MemCopy proc public uses esi edi Source:PTR BYTE,Dest:PTR BYTE,ln:DWORD

; ---------------------------------------------------------
; Copy ln bytes of memory from Source buffer to Dest buffer
; ~~ ~~~~~~ ~~~~
; USAGE:
; invoke MemCopy,ADDR Source,ADDR Dest,4096
;
; NOTE: Dest buffer must be at least as large as the source
; buffer otherwise a page fault will be generated.
; ---------------------------------------------------------

cld
mov esi, [Source] ; Get source data addr
mov edi, [Dest] ; Get Dest data addr
mov ecx, [ln] ; total bytes to copy..

shr ecx, 2 ; divide total bytes/4 (since DWORD loads 4 bytes)
rep movsd ; copy from esi -> edi, 4 byte incraments of data
; untill ecx == 0 (cld makes ecx count down by 1/rep)


mov ecx, [ln] ; what about the remainder from origional div/4?
; we cant forget to copy this as well.. so do by copy
; up to 3 bytes.. so first load # again..
and ecx, 3 ; and out all but the values less than 4 (get remainder)
rep movsb ; Perform remaining data copy of data with BYTES

ret ; done.. all copied from source to dest..

MemCopy endp


I feel very limited with creating a string of fixed length; Is there any other way but using the SysAllocStringByteLen?

Never used it myself.. so i could tell you.. but you could allocate from the Heap or global memory if you want lots of room... not sure which one.. but i believe one can be growable.. if you max it out.

Hope this helps...

NaN
Posted on 2001-09-06 18:06:43 by NaN
Thanks for the explanation! :alright:

but you could allocate from the Heap or global memory
how does that work? Do you have any examples on that?

Thanks
Posted on 2001-09-07 02:58:37 by Butch77
Heap stuff...

invoke GetProcessHeap
invoke HeapAlloc, eax, NULL, # of bytes

and to free the Heap mem...

invoke GetProcessHeap
invoke HeapFree, eax, NULL, heap_mem_handle



Global Mem.. see this thread....


Again, look up these API's to see which one is "growable"

NaN
Posted on 2001-09-07 09:52:52 by NaN