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 Occurencys :DWORD

    push esi ;save esi and edi
    push edi

    mov ecx, text
    xor eax, eax

    mov dl, [ecx]
    inc ecx ;GetStringLength
    cmp dl, "%"
    jne CharNotFound
    inc eax ;Count Occurency of "%"
    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

    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

    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
    cmp al, 65
    jl NoValidHex
    cmp al, 70
    jg SmallHex
    sub al, 55
    jmp NextChar
    cmp al, 97
    jl NoValidHex
    cmp al, 102
    jg NoValidHex
    sub al, 87
    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
    cmp ah, 65
    jl NoValidHex2
    cmp ah, 70
    jg SmallHex2
    sub ah, 55
    jmp EndHex
    cmp ah, 97
    jl NoValidHex2
    cmp ah, 102
    jg NoValidHex2
    sub ah, 87
    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
    mov al, "%" ;Just save an "%" if HexChars weren't valid
    mov [edi], al
    jmp EndLoop
    cmp al, "+" ;if regular Char
    je ReplacePlus
    mov [edi], al
    jmp EndLoop
    ReplacePlus: ;replace "+" with space
    mov al, 32
    mov [edi], al
    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
    mov al, 32
    mov [edi], al
    inc esi
    inc edi
    cmp ln, edi
    jg NoHex
    jmp TheEnd
    mov al, 0 ;terminate String
    mov [edi], al

    mov eax, ReturnString$ ;return String

    pop edi
    pop esi
    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.

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

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

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
; ~~ ~~~~~~ ~~~~
; 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.
; ---------------------------------------------------------

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...

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?

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"

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