Hello!
; ------------------------------------------------------------ ;
;
This is: Win64 Url Encode Byte Array NASM, GCC, GOLINK.
; Author: J.K. Encryptor256
; Date: November 26, 2013
;
; ------------------------------------------------------------ ;
;
Description:
; Url encode byte array.
; Print result.
;
; ------------------------------------------------------------ ;
;
Using:
;
; 1.
NASM: (
http://nasm.us/)
;
; "The Netwide Assembler, NASM,"
; "is an 80x86 and x86-64 assembler designed"
; "for portability and modularity."
;
; 2.
MINGW64-GCC: (
http://mingw-w64.sourceforge.net/)
;
; "Mingw-w64 delivers runtime, headers and libs for"
; "developing both 64 bit (x64) and 32 bit (x86) windows"
; "applications using GCC and other free software compilers."
;
; 3.
GoLink: (
http://www.godevtool.com/)
;
; "Jeremy Gordon's Go Tools for Win32 and Win64:"
; "assembler, resource compiler,"
; "linker, debugger and information"
;
; ------------------------------------------------------------ ;
;
Compile:
;
; 1.
NASM.EXE:
; "-f win64 main.asm -o main.obj"
;
; Output size: 1.64 KB (1,688 bytes)
;
; Choose your linker:
;
; 2.
GCC.EXE:
; "main.obj -m64 -o main.exe"
;
; Output size: 43.3 KB (44,395 bytes)
;
; 3.
GoLink.EXE:
; "/entry main /console main.obj MSVCRT.dll"
;
; Output size: 2.00 KB (2,048 bytes)
;
; ------------------------------------------------------------ ;
Info:
This procedure "urlEncodeByteArray" became pretty interesting,
it uses internal procedure. First time it run's loop cycle,
it determines the size of result buffer. Second time, it calls,
internal procedure and now it updates result buffer, using
the same cycle again.
Procedure:
; -----------------------------------------------------------;
;
; Procedure: urlEncodeByteArray
;
; Encodes byte array (RFC1738)
;
; RCX - src buffer address
; RDX - src buffer len
; R8 - hex idicator
;
; Usage:
;
; Result of this example,
; should be: ,124Vx,9A,BC,DE,F1,23Eg,89,AB,CD,EF,124Vx,9A
; Be aware that, using HEX idicator '%' will produce
; visual glitch with "printf", because '%' is a special char.
;
; ...
; align 8
; txt_test:db 0x12,0x34,0x56,0x78,0x9a,
; db 0xbc,0xde,0xf1,0x23,0x45,
; db 0x67,0x89,0xab,0xcd,0xef,
; db 0x12,0x34,0x56,0x78,0x9a
; txt_test_len equ ($ - txt_test)
; ...
;
; mov rdx,txt_test_len
; mov rcx,txt_test
; mov r8,','
; call urlEncodeByteArray
; mov rbx,rax
;
; mov rcx,rax
; call printf
;
; mov rcx,rbx
; call free
;
;
; Returns a pointer to null terminated string buffer.
; Null terminator are excluded from buffer len.
; Returned buffer must be freed by "malloc".
;
; Returns a pointer to buffer into RAX.
; Returns a buffer len into RCX.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; -----------------------------------------------------------;
align 8
urlEncodeByteArray:
; Check args
xor rax,rax
cmp rcx,rax
je .earlyQuit
cmp rdx,rax
jne .proceed
.earlyQuit:
; Set error n quit
stc
ret
.proceed:
; Save args
mov qword [rsp+8*1],rcx; src buffer address
mov qword [rsp+8*2],rdx; src buffer len
mov qword [rsp+8*3],r8; hex indicator
; r8 - hex indicator,
; example value ('%', or '.') => (%HH or .HH)
; Create stack
push rbp
mov rbp,rsp
push rbx
push r12
push r13
push r14
push rsi
push rdi
lea rsp,[rsp-(8*4)]
; 1. Save src buffer address and len
; rcx is already set
; rdx is already set
mov rsi,rcx ; address
mov r12,rdx ; len
mov r14,rcx
; 2. Determine dst buffer len (Loop)
; rsi - src buffer address
; rcx - src buffer len
; rdx - dst buffer len
; bx - temporary usage
; r13 - must be zero
mov rcx,r12
xor rdx,rdx
xor r13,r13
; 3. Internal procedure
.lblProcedure:
cld
; 4. Internal loop
.lblLoop:
lodsb
; 4.1. Individual
cmp al,byte ('.')
je .lblStoreSingle
cmp al,byte ('-')
je .lblStoreSingle
cmp al,byte ('_')
je .lblStoreSingle
cmp al,byte ('~')
je .lblStoreSingle
; 4.2. 0-9
cmp al,byte ('0')
setge bl
cmp al,byte ('9')
setle bh
and bl,bh
jnz .lblStoreSingle
; 4.3. a-z
cmp al,byte ('a')
setge bl
cmp al,byte ('z')
setle bh
and bl,bh
jnz .lblStoreSingle
; 4.4. A-Z
cmp al,byte ('A')
setge bl
cmp al,byte ('Z')
setle bh
and bl,bh
jnz .lblStoreSingle
.incBy3:
add rdx,byte (2)
; 3.1. Functionoid - store '%' 'H' 'H'
cmp r13b, byte (1)
jne .lblContinue
; 3.2. Store '%'
mov ah,al; Save al
;mov al,byte ('%')
mov al,r8b
stosb
; 3.3. Build n Store hex part HH
mov al,ah; Restore al
and al,0xF0
and ah,0x0F
shr al,byte (0x04)
.lblAL:
cmp al,byte (0x09)
jle .lblAH
add al,byte (0x07)
.lblAH:
cmp ah,byte (0x09)
jle .lblDone
add ah,byte (0x07)
.lblDone:
add ax,word (0x3030)
stosw
jmp .lblContinue
.lblStoreSingle:
; 3.4. Functionoid - store 'c'
cmp r13b, byte (1)
jne .lblContinue
; Store char
stosb
.lblContinue:
inc rdx
loop .lblLoop
; 3.5. Functionoid - quit
cmp r13b, byte (1)
jne .fnQuit
; Set null terminator byte
mov al,byte (0)
stosb
ret
.fnQuit:
; 5. Save hex idicator
mov rbx,r8
; 6. Allocate buffer
mov rcx,rdx
inc rcx
call malloc
xor rdx,rdx
cmp rax,rdx
je .quitError
; 7. Restore hex idicator
mov r8,rbx
; 8. Prepare procedure params
mov rsi,r14
mov rdi,rax
mov rcx,r12
xor rdx,rdx
mov r13b,byte (1)
mov r14,rax ; Save buffer address from malloc
; 9. Call internal procedure
call .lblProcedure
jmp .quitSuccess
.quitError:
; Set error
stc
jmp .quit
.quitSuccess:
; 10. Set return value
mov rax,r14 ; address of buffer
mov rcx,rdx ; buffer len
; 11. Set success
clc
.quit:
; 12. Clear stack n quit
lea rsp,[rsp+(8*4)]
pop rdi
pop rsi
pop r14
pop r13
pop r12
pop rbx
pop rbp
ret
Output:
[code begin]
urlEncodeByteArray: .124Vx.9A.BC.DE.F1.23Eg.89.AB.CD.EF.124Vx.9A
[code end]
Video:
Watch source code and run time demo on youtube:
Win64 Url Encode Byte Array NASM GCC GOLINKAttachment:
Added attachment named: win64_urlencodebytearray_nasm_gcc_golink.zip, which includes, main compile file of source code: "main.asm".
An that's it,
Bye,
Encryptor256!!!