News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Create a linked queue use masm32

Started by enevil, May 24, 2011, 03:45:23 AM

Previous topic - Next topic

enevil

hi guy:
      i want to use mams32 to create a linked queue,but there is some question in the program

.386
.model flat,stdcall
option casemap:none


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

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

include \masm32\macros\macros.asm
QNode struct
NextPtr dd ?
UserData dd ?
QNode ends

Queue struct
frontPtr dd ?
rearPtr dd ?
Queue ends

InitQueue proto :DWORD
enQueue proto :DWORD,:DWORD
deQueue proto :DWORD,:DWORD
IsQueueEmpty proto :DWORD
ClearQueue proto :DWORD

.const

.data

.data?
hHeap dd ?
lQueue dd ?
lpBuffer dd ?
.code
start:
invoke InitQueue,addr lQueue
invoke enQueue,addr lQueue,CTXT("abcdefg")
invoke enQueue,addr lQueue,CTXT("ccccccc")
invoke enQueue,addr lQueue,CTXT("dddddddddd")
invoke enQueue,addr lQueue,CTXT("adfasdfasdfasd")


.while TRUE
invoke IsQueueEmpty,lQueue
.break .if(eax==1)
invoke deQueue,addr lQueue,addr lpBuffer
invoke StdOut,lpBuffer
invoke StdOut,CTXT(0DH,0AH)
.endw
invoke StdOut,CTXT("OK!!",0dh,0ah)
invoke ClearQueue,addr lQueue
invoke ExitProcess,0

InitQueue proc lq:DWORD

invoke HeapCreate,0,0,0
; .if eax==NULL
; invoke StdOut,CTXT("Heap Create Failed!!",0dh,0ah)
; mov eax,FALSE
; ret
; .endif
mov hHeap,eax

invoke HeapAlloc,hHeap,0,sizeof Queue
; .if eax==NULL
; invoke StdOut,CTXT("Alloc Mem Failed!!",0dh,0ah)
; mov eax,FALSE
; ret
; .endif
mov (Queue ptr [eax]).frontPtr,NULL
mov (Queue ptr [eax]).rearPtr,NULL
mov edx,lq
mov [edx],eax
ret
InitQueue endp

enQueue proc lq:DWORD,pdata:DWORD
LOCAL tmp:DWORD

invoke HeapAlloc,hHeap,0,sizeof QNode
mov (QNode ptr [eax]).NextPtr,NULL
push pdata
pop (QNode ptr [eax]).UserData
mov tmp,eax
;
mov eax,lq
mov edx,[eax]

mov ecx,(Queue ptr [edx]).rearPtr

.if ecx==NULL
mov eax,tmp
mov (Queue ptr [edx]).frontPtr,eax
mov (Queue ptr [edx]).rearPtr,eax
.else
mov eax,tmp
mov (QNode ptr [ecx]).NextPtr,eax
mov (Queue ptr [edx]).rearPtr,eax
.endif

xor eax,eax
ret
enQueue endp

deQueue proc uses esi edi ebx lq:DWORD,ppdata:DWORD


mov eax,lq
mov eax,[eax]

mov ecx,ppdata
mov esi,(Queue ptr [eax]).frontPtr
mov edx,(QNode ptr [esi]).UserData
mov [ecx],edx

mov edi,(Queue ptr [eax]).rearPtr
.if esi==edi
mov (Queue ptr [eax]).frontPtr,NULL
mov (Queue ptr [eax]).rearPtr,NULL
.else
push (QNode ptr [esi]).NextPtr
pop (Queue ptr [eax]).frontPtr
.endif

invoke HeapFree,hHeap,0,eax

xor eax,eax
ret
deQueue endp

IsQueueEmpty proc uses esi edi lq:DWORD

mov eax,lq
mov esi,(Queue ptr [eax]).frontPtr
mov edi,(Queue ptr [eax]).rearPtr

.if esi==NULL && edi==NULL
mov eax,1
.else
mov eax,0
.endif

ret
IsQueueEmpty endp

ClearQueue proc lq:DWORD

; mov eax,lq
mov ebx,[lq]
mov esi,(Queue ptr [ebx]).frontPtr
mov edi,(Queue ptr [ebx]).rearPtr

.if !(esi==NULL && edi==NULL)

.while esi!=NULL
mov eax,(QNode ptr [esi]).NextPtr
mov (Queue ptr [eax]).frontPtr,eax
invoke HeapFree,hHeap,0,esi
mov esi,(Queue ptr [ebx]).frontPtr
.endw
mov (Queue ptr [ebx]).rearPtr,NULL
.endif
invoke HeapFree,hHeap,0,eax
invoke HeapDestroy,hHeap
xor eax,eax
ret
ClearQueue endp
end start

sorry,my english is poor

jj2007

One problem is here:
deQueue proc uses esi edi ebx lq:DWORD,ppdata:DWORD

mov eax,lq
; mov eax,[eax] ; <<<< check this

mov ecx,ppdata
mov esi,(Queue ptr [eax]).frontPtr
.if !esi
MsgBox 0, "Esi is zero", "Hi", MB_OK
exit
.endif

dedndave

a simple way is to access structure members like this
       mov     eax,[esi].QNode.NextPtr

another way is to use ASSUME to tell the assembler that ESI is a pointer to a structure
it is probably cleaner, but also more likely to cause problems   :P

your code is probably close to working   :U
you just need a little syntax cleanup
i just got up - first cup of coffee - lol
maybe i will look it over again a little later

jj2007

Dave, his ...
mov esi, (Queue ptr [eax]).frontPtr
... syntax works fine, but there is a bit too much dereferencing. Commenting out the mov eax, [eax] gets it running for a few loops, then bang again.

enevil

Quote from: jj2007 on May 24, 2011, 07:51:48 AM
One problem is here:
deQueue proc uses esi edi ebx lq:DWORD,ppdata:DWORD

mov eax,lq
; mov eax,[eax] ; <<<< check this

mov ecx,ppdata
mov esi,(Queue ptr [eax]).frontPtr
.if !esi
MsgBox 0, "Esi is zero", "Hi", MB_OK
exit
.endif

.thanks
.it does not work normally
the queue is a pointer to Queue struct

the lq is a pointer to the queue  except in the function IsQueueEmpty
so can you give a complete code


baltoro

ENEVIL,
i'm curious,...as you probably are aware, the C++ language has an implementation of a queue template class.
Are you trying to create something similar in assembly language,...or, is this just a simple queue ?
Years ago, I was reading through the book describing the C++ Standard Template Library container types, and, the author mentions that each container class has a number of internal routines to order, check the integrity, and maintain a coherent memory structure for the data. The authors said that this was the most difficult part to get correct: the memory allocations, checking, and re-ordering of elements so that memory usage was efficient, and memory fragmentation didn't become cumbersome.
If you are just doing a simple implementation, this won't be an issue,...but, if you plan to add routines that will create a large data structure, memory fragmentation will adversly affect your program.
Here is a link to: Standard Template Library Programmer's Guide,...it might give you some ideas (then again, it might just confuse you).
Baltoro

qWord

Quoteinclude masm32rt.inc
.686p

NODE struct
   pNext   PVOID   ?
   pPrev   PVOID   ?
   pData   PVOID   ?
NODE ends
PNODE typedef ptr NODE

QUEUE struct
   nNodes      DWORD ?
   pFirst      PNODE ?
   pLast      PNODE ?   
   dwUserData1   DWORD ?
QUEUE ends
PQUEUE typedef ptr QUEUE

.code
CreateQueue proc ppQueue: ptr PQUEUE , dwUserData:DWORD
   
   mov eax,alloc(SIZEOF QUEUE)
   mov edx,ppQueue
   mov PQUEUE ptr [edx],eax
   m2m [eax].QUEUE.dwUserData1,dwUserData

   ret
   
CreateQueue endp

QueueInsert proc pQueue:PQUEUE,pData:PVOID
   
   mov edx,alloc(SIZEOF NODE)
   m2m [edx].NODE.pData,pData
   
   mov eax,pQueue
   .if [eax].QUEUE.nNodes
      inc [eax].QUEUE.nNodes
      mov ecx,[eax].QUEUE.pFirst
      mov [eax].QUEUE.pFirst,edx
      mov [edx].NODE.pNext,ecx
      mov [ecx].NODE.pPrev,edx
      m2m [edx].NODE.pData,pData
   .else
      mov [eax].QUEUE.nNodes,1
      mov [eax].QUEUE.pFirst,edx
      mov [eax].QUEUE.pLast,edx
      m2m [edx].NODE.pData,pData
   .endif
   
   ret
   
QueueInsert endp

QueueGet proc uses ebx edi pQueue:PQUEUE
   
   mov ebx,pQueue
   .if [ebx].QUEUE.nNodes
      mov edi,[ebx].QUEUE.pLast
      m2m [ebx].QUEUE.pLast,[edi].NODE.pPrev
      mov edi,[edi].NODE.pData
      free edi
      
      .if [ebx].QUEUE.nNodes == 1
         mov [ebx].QUEUE.pFirst,0
         mov [ebx].QUEUE.pLast,0
      .endif
      dec [ebx].QUEUE.nNodes
   
      mov eax,edi
      ret
   .else
      xor eax,eax
      ret
   .endif
   
   ret
   
QueueGet endp

DestroyQueue proc uses esi edi pQueue:PQUEUE
   
   mov eax,pQueue
   mov esi,[eax].QUEUE.nNodes
   mov edi,[eax].QUEUE.pFirst
   .while esi
      mov edx,edi
      mov edi,[edi].NODE.pNext
      free edx      
      dec esi
   .endw
   free pQueue
   
   ret
   
DestroyQueue endp

main proc
LOCAL pQueue:PVOID
   
   invoke CreateQueue,ADDR pQueue,0
   fn QueueInsert,pQueue,"1"
   fn QueueInsert,pQueue,"2"
   fn QueueInsert,pQueue,"3"
   fn QueueInsert,pQueue,"4"
   
   .while 1
      .if rv(QueueGet,pQueue)
         print eax,13,10
      .else
         .break   
      .endif
   .endw
   invoke DestroyQueue,pQueue
   inkey
   exit
   
main endp
end main
FPU in a trice: SmplMath
It's that simple!

enevil

qWord 
Thank you
But i want to Create it by myself,could you help me to pick up the error
sorry my english is poor

RuiLoureiro

#8
Hi
     »»» But i want to Create it by myself,could you help me to pick up the error
     
    1.  If you use «invoke InitQueue, addr lQueue»

        then you dont need to use
        «invoke enQueue, ADDR lQueue, CTXT("abcdefg")»

        but only
        «invoke enQueue, lQueue, CTXT("abcdefg")»

    2. The same for other similar procs

    3. there is another error elsewhere, try to find it
        See deQueue procedure. It seems it is not correct

Quote       
enQueue  proc   lq:DWORD, pdata:DWORD
      LOCAL  tmp:DWORD

   invoke HeapAlloc, hHeap, 0, sizeof QNode
   mov (QNode ptr [eax]).NextPtr,NULL
   push pdata
   pop (QNode ptr [eax]).UserData
   mov tmp,eax
;   

      mov   edx, lq
   mov   ecx,(Queue ptr [edx]).rearPtr
   
   .if ecx==NULL
      mov eax, tmp
      mov (Queue ptr [edx]).frontPtr,eax
      mov (Queue ptr [edx]).rearPtr,eax
   .else
      mov eax,tmp
      mov (QNode ptr [ecx]).NextPtr,eax
      mov (Queue ptr [edx]).rearPtr,eax
   .endif
   
   ret
enQueue endp

RuiLoureiro

enevil,
         i read and i run your prog
         and i didnt understand what you want to do

        When you invoke enQueue... you want to build a structure
        like this (you alloc 4 blocks of memory Addr1, Addr2, Addr3, Addr4):

        Addr1:  "abcdefg"               pNext= Addr2
        Addr2:  "ccccccc"               pNext= Addr3
        Addr3:  "dddddddddd"            pNext= Addr4
        Addr4:  "adfasdfasdfasd"        pNext= 0
       
        a) Is this correct ?

        If it is correct, after those 4 strings, we have
       
                            frontPtr = Addr1
                            rearPtr  = Addr4
           
        b) Is this correct ?

        When we want to get the strings from the Queue
        we need to do this:

                       pNext = frontPtr
                       (If pNext = 0 the Queue is empty)
                       ...
                       pNext    = NextPtr
                       frontPtr = pNext

        If iam wrong, explain your algo, may be we can help you

RuiLoureiro

        This works but you need to see ClearQueue
       
 

include \masm32\include\masm32rt.inc

;.386
;.model flat,stdcall
;option casemap:none


;include \masm32\include\windows.inc
;include \masm32\include\kernel32.inc
;include \masm32\include\user32.inc
;include \masm32\include\masm32.inc

;includelib \masm32\lib\kernel32.lib
;includelib \masm32\lib\user32.lib
;includelib \masm32\lib\masm32.lib

;include \masm32\macros\macros.asm

QNode struct
NextPtr dd ?
UserData dd ?
QNode ends

Queue struct
frontPtr dd ?
rearPtr dd ?
Queue ends

InitQueue proto :DWORD
enQueue proto :DWORD,:DWORD
deQueue proto :DWORD,:DWORD
IsQueueEmpty proto :DWORD
ClearQueue proto :DWORD

.const

.data

.data?
hHeap dd ?
lQueue dd ?
lpBuffer dd ?
.code
start:
invoke InitQueue, addr lQueue
invoke enQueue, lQueue,CTXT("abcdefg")
invoke enQueue, lQueue,CTXT("ccccccc")
invoke enQueue, lQueue,CTXT("dddddddddd")
invoke enQueue, lQueue,CTXT("adfasdfasdfasd")


.while TRUE
invoke IsQueueEmpty, lQueue
            cmp    eax, 1
            je     short _end
           
invoke deQueue, lQueue, addr lpBuffer
invoke StdOut, lpBuffer
invoke StdOut,CTXT(0DH,0AH)
      ;inkey

.endw
_end:
invoke StdOut, CTXT("OK!!",0dh,0ah)
invoke ClearQueue, lQueue

      inkey

invoke ExitProcess,0
;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
InitQueue proc lq:DWORD

invoke HeapCreate,0,0,0
.if eax==NULL
invoke StdOut,CTXT("Heap Create Failed!!",0dh,0ah)
mov eax,FALSE
ret
.endif
mov hHeap,eax

invoke HeapAlloc,hHeap,0,sizeof Queue
.if eax==NULL
invoke StdOut,CTXT("Alloc Mem Failed!!",0dh,0ah)
mov eax,FALSE
ret
.endif
mov    (Queue ptr [eax]).frontPtr,NULL
mov    (Queue ptr [eax]).rearPtr,NULL
mov    edx,lq
mov    [edx],eax
ret
InitQueue endp

enQueue  proc   lq:DWORD, pdata:DWORD

invoke HeapAlloc, hHeap, 0, sizeof QNode
mov (QNode ptr [eax]).NextPtr,NULL
push pdata
pop (QNode ptr [eax]).UserData
mov ebx,eax
;
      mov   edx, lq
mov   ecx,(Queue ptr [edx]).rearPtr

.if ecx==NULL
mov (Queue ptr [edx]).frontPtr,ebx
mov (Queue ptr [edx]).rearPtr,ebx
.else
mov (QNode ptr [ecx]).NextPtr,ebx
mov (Queue ptr [edx]).rearPtr,ebx
.endif

ret
enQueue endp

deQueue proc uses esi edi ebx lq:DWORD,ppdata:DWORD

mov eax,lq

mov ecx,ppdata
mov esi,(Queue ptr [eax]).frontPtr
;mov edi,(Queue ptr [eax]).rearPtr

;mov edx,(QNode ptr [esi]).UserData
;mov [ecx],edx



.if esi==0
;mov (Queue ptr [eax]).frontPtr,NULL
mov (Queue ptr [eax]).rearPtr,NULL
.else

      mov edx,(QNode ptr [esi]).UserData
      mov [ecx],edx

push (QNode ptr [esi]).NextPtr
pop (Queue ptr [eax]).frontPtr
.endif

invoke HeapFree, hHeap, 0, esi
ret
deQueue endp

IsQueueEmpty proc lq:DWORD

mov eax, lq
mov ecx,(Queue ptr [eax]).frontPtr
;mov edx,(Queue ptr [eax]).rearPtr

.if ecx==NULL                  ;&& edx==NULL
mov eax,1
.else
mov eax,0
.endif

ret
IsQueueEmpty endp

ClearQueue proc lq:DWORD

mov ebx, lq

mov esi,(Queue ptr [ebx]).frontPtr
mov edi,(Queue ptr [ebx]).rearPtr

.if !(esi==NULL && edi==NULL)

.while esi!=NULL
mov eax,(QNode ptr [esi]).NextPtr
mov (Queue ptr [eax]).frontPtr,eax
invoke HeapFree,hHeap,0,esi
mov esi,(Queue ptr [ebx]).frontPtr
.endw
mov (Queue ptr [ebx]).rearPtr,NULL
.endif
invoke HeapFree,hHeap,0,eax
invoke HeapDestroy,hHeap
xor eax,eax
ret
ClearQueue endp
end start
 

RuiLoureiro

        Replace ClearQueue by this:       
 
ClearQueue proc lq:DWORD

mov ebx, lq

mov esi,(Queue ptr [ebx]).frontPtr
mov edi,(Queue ptr [ebx]).rearPtr

.if !(esi==NULL && edi==NULL)

.while esi!=NULL
mov eax, (QNode ptr [esi]).NextPtr
mov (Queue ptr [ebx]).frontPtr, eax

invoke HeapFree,hHeap,0,esi
mov esi,(Queue ptr [ebx]).frontPtr
.endw
.endif

invoke HeapFree, hHeap, 0, ebx
invoke HeapDestroy, hHeap
xor eax,eax
ret
ClearQueue endp