[MASM] - Small Vector 'Class'

01/30/2014 22:44 ​Tension#1
Hey,
ich brauchte eine Art Vector-Class in MASM für das Handling von Struct-Arrays usw. ( allgemein ist es dann handlicher meiner Meinung nach ), also hab ich mich entschlossen eine Klasse zu schreiben bzw. eine ASM-Datei.

hier ist erstmal der code von Vector.asm:
Code:
;===================================;
;=	        Vector Class           =;
;= Author: Ten$ion                 =;
;= Date: 01/30/2014                =;
;= Language: MASM                  =;
;===================================;

vPushBack					proto	:DWORD, :DWORD
vPopBack					proto	:DWORD
vGet						proto	:DWORD, :DWORD
vSet						proto	:DWORD, :DWORD, :DWORD
vInsert						proto	:DWORD, :DWORD, :DWORD
vRemove						proto	:DWORD, :DWORD
memcpy						proto	:DWORD, :DWORD, :DWORD

;==================;
;=  String Macro  =;
;==================;
_str macro x:VARARG	
	LOCAL txt
	.data
		txt	db	x,0
		align 4
	.code
	exitm <addr txt>
endm

;===================;
;= ErrorBox Macro  =;
;===================;
_error macro _text
	pushad
	invoke MessageBox, 0, _text, _str('Error'), MB_ICONERROR
	popad
endm


.const
;Main struct
Vector struct
	dwElementSize			DWORD		?			; Size of the Element Type
	dwSize					DWORD		?			; Size of the Vector
	dwCount					DWORD		?			; Element Count of Vector
	lpData					DWORD		?			; Pointer to the Data from the Vector
Vector ends

;Allocates Memory
_alloc	macro _size
	invoke GetProcessHeap
	invoke HeapAlloc, eax, HEAP_ZERO_MEMORY, _size
endm

;Frees Memory
_free	macro _addr
	invoke GetProcessHeap
	invoke HeapFree, eax, 0, _addr
endm

.code

;Pushes an element into the vector
vPushBack					proc	lpVector:DWORD, lpData:DWORD
	LOCAL oldbuf:DWORD, newbuf:DWORD
	pushad
	mov esi, lpVector
	assume esi:ptr Vector
	cmp [esi].dwCount, 0
	je @FirstEntry
	_alloc [esi].dwSize
	mov oldbuf, eax
	invoke memcpy, oldbuf, [esi].lpData, [esi].dwSize
	mov ebx, [esi].dwSize
	add ebx, [esi].dwElementSize
	_alloc ebx
	mov newbuf, eax
	invoke memcpy, newbuf, [esi].lpData, [esi].dwSize
	mov edx, [esi].dwSize
	add edx, newbuf
	invoke memcpy, edx, addr lpData, [esi].dwElementSize
	push newbuf
	pop [esi].lpData
	inc [esi].dwCount
	mov ebx, [esi].dwSize
	add ebx, [esi].dwElementSize
	mov [esi].dwSize,  ebx
	_free oldbuf
	jmp @Done
	@FirstEntry:
	_alloc [esi].dwElementSize
	mov [esi].lpData, eax
	push [esi].dwElementSize
	pop [esi].dwSize
	inc [esi].dwCount
	invoke memcpy, [esi].lpData, addr lpData, [esi].dwElementSize
	@Done:
	assume esi:ptr NOTHING
	popad
	
	ret

vPushBack endp

;Pops an element from the vector
vPopBack					proc	lpVector:DWORD
	LOCAL newbuf:DWORD
	mov esi, lpVector 
	assume esi:ptr Vector
	mov edi, [esi].lpData
	mov ebx, [esi].dwSize
	cmp ebx, 0
	je @IsZero
	sub ebx, [esi].dwElementSize
	_alloc ebx
	mov newbuf, eax
	invoke memcpy, newbuf, [esi].lpData, ebx
	_free [esi].lpData
	push newbuf
	pop [esi].lpData
	dec [esi].dwCount
	mov ebx, [esi].dwElementSize
	sub [esi].dwSize, ebx
	jmp @Done
	@IsZero:
	_error _str('Cannot popback, the vector is empty.')
	@Done:
	assume esi:ptr NOTHING
	ret
	
vPopBack endp

;Returns an element from the given index
vGet						proc	lpVector:DWORD, lpPos:DWORD
	LOCAL data:DWORD
	mov esi, lpVector
	assume esi:ptr Vector
	mov ebx, lpPos
	mov ecx, [esi].dwCount
	dec ecx
	cmp ebx, ecx
	jg @IsBigger
	imul ebx, [esi].dwElementSize
	lea edx, [esi].lpData
	add [edx], ebx
	invoke memcpy,addr data, [edx], [esi].dwElementSize
	mov eax, data
	jmp @Done
	@IsBigger:
	_error _str('Position out of Range')
	@Done:
	assume esi:ptr NOTHING	
	ret

vGet endp

;Sets an element from the given index and data
vSet					proc		lpVector:DWORD, lpPos:DWORD, lpData:DWORD
	mov esi, lpVector
	assume esi:ptr Vector
	mov ebx, lpPos
	mov ecx, [esi].dwCount
	dec ecx
	cmp ebx, ecx
	jg @IsBigger
	imul ebx, [esi].dwElementSize
	lea edx, [esi].lpData
	add [edx], ebx
	invoke memcpy,[edx],addr lpData, [esi].dwElementSize
	jmp @Done
	@IsBigger:
	_error _str('Position out of Range')
	@Done:
	assume esi:ptr NOTHING
	ret

vSet endp

;Inserts an element into the Vector
vInsert					proc	lpVector:DWORD, lpPos:DWORD, lpData:DWORD
	LOCAL newbuf:DWORD, firstsize:DWORD
	mov esi, lpVector
	assume esi:ptr Vector
	mov ebx, lpPos
	mov ecx, [esi].dwCount
	dec ecx
	cmp ebx, ecx
	jg @IsBigger
	cmp lpPos, 0
	je @IsZero
	mov ebx, [esi].dwSize
	add ebx, [esi].dwElementSize
	_alloc ebx
	mov newbuf, eax
	mov ebx, lpPos
	imul ebx, [esi].dwElementSize
	mov firstsize, ebx
	invoke memcpy, newbuf, [esi].lpData, firstsize
	mov edi, newbuf
	add edi, [esi].dwElementSize
	invoke memcpy, edi, addr lpData, [esi].dwElementSize
	mov ebx, [esi].dwCount
	sub ebx, lpPos
	imul ebx, [esi].dwElementSize
	mov edi, newbuf
	add edi, firstsize
	add edi, [esi].dwElementSize
	mov edx, [esi].lpData
	add edx, firstsize
	invoke memcpy, edi, edx, ebx
	inc [esi].dwCount
	mov ebx, [esi].dwElementSize
	add [esi].dwSize, ebx
	_free [esi].lpData
	push newbuf
	pop [esi].lpData
	jmp @Done
	@IsZero:
	mov ebx, [esi].dwSize
	add ebx, [esi].dwElementSize
	_alloc ebx
	mov newbuf, eax
	invoke memcpy, newbuf, addr lpData, [esi].dwElementSize
	mov ebx, [esi].dwCount
	imul ebx, [esi].dwElementSize
	mov edi, newbuf
	add edi, [esi].dwElementSize
	mov edx, [esi].lpData
	invoke memcpy, edi, edx, ebx
	inc [esi].dwCount
	mov ebx, [esi].dwElementSize
	add [esi].dwSize, ebx
	_free [esi].lpData
	push newbuf
	pop [esi].lpData
	jmp @Done
	@IsBigger:
	_error _str('Position out of Range')
	@Done:
	assume esi:ptr NOTHING
	ret

vInsert endp

;Removes an element from the Vector
vRemove 		proc	lpVector:DWORD, lpPos:DWORD
	LOCAL newbuf:DWORD, firstsize:DWORD
	mov esi, lpVector
	assume esi:ptr Vector
	mov ebx, lpPos
	mov ecx, [esi].dwCount
	dec ecx
	cmp ebx, ecx
	jg @IsBigger
	mov ebx, [esi].dwSize
	sub ebx, [esi].dwElementSize
	_alloc ebx
	mov newbuf, eax
	mov ebx, lpPos
	imul ebx, [esi].dwElementSize
	mov firstsize, ebx
	invoke memcpy, newbuf, [esi].lpData, firstsize
	mov ebx, [esi].dwCount
	sub ebx, lpPos
	dec ebx
	imul ebx, [esi].dwElementSize
	mov edi, newbuf
	add edi, firstsize
	mov edx, [esi].lpData
	add edx, firstsize
	add edx, [esi].dwElementSize
	invoke memcpy, edi, edx, ebx
	inc [esi].dwCount
	mov ebx, [esi].dwElementSize
	add [esi].dwSize, ebx
	_free [esi].lpData
	push newbuf
	pop [esi].lpData
	jmp @Done
	@IsBigger:
	_error _str('Position out of Range')
	@Done:
	assume esi:ptr Nothing
	ret
vRemove endp

;Clears the Vector
vClear			proc	lpVector:DWORD
	mov esi, lpVector
	assume esi:ptr Vector
	mov [esi].dwSize, 0
	mov [esi].dwCount, 0
	_free [esi].lpData
	mov [esi].lpData, 0
	assume esi:ptr NOTHING
	ret

vClear endp

;Copies memory
memcpy			proc	output:DWORD, input:DWORD, len:DWORD
	pushad
	mov esi, input
	mov edi, output
	mov ecx, len
	rep movsb
	popad
	ret

memcpy endp

Und hier noch ein Beispiel zur Anwendung:
Code:
.386
.model flat,stdcall
option casemap:none

include windows.inc
include msvcrt.inc
include kernel32.inc
include user32.inc
include masm32.inc

includelib msvcrt.lib
includelib kernel32.lib
includelib user32.lib
includelib masm32.lib

include Vector.asm


.const

.data?

.data
szBuffer				db	MAX_PATH		dup(0)

Vec		Vector <4,0,0,0>

.code

start:
	invoke vPushBack, addr Vec, _str('Hallo wie gets?')
	invoke vPushBack, addr Vec, _str('Halloie gehts?')
	invoke vPushBack, addr Vec, _str('Hallo wiehts?')
	invoke vPushBack, addr Vec, _str('He gehts?')
	invoke vPushBack, addr Vec, _str('Hallo wie ts?')
	invoke vInsert, addr Vec, 0, _str('123546')
	invoke vGet, addr Vec, 0
	invoke vClear, addr Vec
	invoke vPushBack, addr Vec, _str('123123123123123123123123123')
	invoke vGet, addr Vec, 0
	mov esi, eax
	invoke wsprintf, addr szBuffer, _str('%s'), esi
	invoke MessageBox,0, addr szBuffer,0,0
	invoke ExitProcess, 0
end start
ich denke es sollte klar sein wie es funktioniert.
Wieso man bei Strings die größe 4 benutzt ist einfach: Man pusht die Adresse des Strings in den Vector nicht den String selbst und die Adresse ist immer ein DWORD also 4 Bytes groß.

Vielleicht könnt ihr ja damit auch was anfangen.

MfG,

Ten$ion