News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Make procedure

Started by shekel, May 23, 2015, 12:51:36 PM

Previous topic - Next topic

shekel

Sorry by my English

Im working with files.. in my case i want to make a function that count the lines of the file and other function that giveme the text in the line..

Im doing this:

ReadFile proc Line:DWORD
LOCAL szFile[MAX_PATH]:DWORD
LOCAL hRead:HANDLE
LOCAL hMemory:HANDLE
LOCAL pMemory :DWORD                             
LOCAL SizeReadWrite :DWORD     
LOCAL sizee: DWORD             

LOCAL CurrentLine:DWORD   

invoke lstrcpy, addr szFile, chr$("C:\file.txt") 
invoke CreateFile, addr szFile,GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
mov hRead, eax
invoke GetFileSize, hRead, NULL
mov tamano, eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT, addr sizee
        mov  hMemory,eax
        invoke GlobalLock,hMemory
        mov  pMemory,eax 
invoke ReadFile, hRead, pMemory, addr tamano , addr SizeReadWrite, 0

; new line --> '0D 0A'
invoke lstrlen, pMemory
mov ecx, eax
mov esi, pMemory 
xor edx, edx
letter:
mov al, [esi]
.if al == 0Dh
inc esi
mov al, [esi]
.if al == 0Ah
; line
inc edx             ; HERE is the number of lines
mov bx, 0
mov [esi-1], bx
.endif
.endif
inc esi
loop letter

mov eax, [Line]
dec eax
.if eax > edx
xor esi, esi
ret
.endif

mov [CurrentLine], 1
mov esi, pMemory
mov ecx, edx
line:
mov eax, [CurrentLine]
.if [Line] == eax
mov ecx, 1
.else
invoke lstrlen, esi
add esi, eax
add esi, 2h
inc [CurrentLine]
.endif
loop line




invoke MessageBox, NULL, esi, chr$("aa"), MB_OK

invoke GlobalUnlock, hMemory
invoke GlobalFree, hMemory
invoke CloseHandle, hRead

ret

ReadFile endp


I dont know if this is a beautiful way.. but it works..

If now i want get the count of the lines, for example, getCountLines proto, i need rewrite the createfile, open memory, read file, etc..

Or how can i do...
pseudocode:

       getCountLines proc
            invoke MyFunctionThatOpenFileAndReserveMemory
            mov eax, HERE_IS_THERE_MY_LINES
            invoke CloseAllTheHandlesOfTheFileAndMemory
       getCountLines endp

       getLine proc Line:DWORD
            invoke MyFunctionThatOpenFileAndReserveMemory
            mov esi, MOVE_HERE_THE_TEXT_OF_THE_LINE
            invoke CloseAllTheHandlesOfTheFileAndMemory
       getLine endp

Or if i create a single function with one "parameter" and if this value is "-1" that meaning that want the count of the line??


Sorry for do this question and my bad english but im trying to learn

rrr314159

shekel no need to apologize your English, it's quite good, almost seems like a native speaker pretending otherwise!

Quote from: shekelbut it works

- But it can't work.

The proc can't be named ReadFile - in fact you call the Windows function ReadFile in it.
And, "tamano" (strange name) is a "Symbol not defined" - will give an error.

But this proc that you wrote yourself works for you; and, it's a pretty sophisticated piece of code, so clearly u know MASM well! That's great! You've merely made a couple typos posting it (the two mentioned above, couple more also). Just fix it up so we can run it also, (include a start: routine calling it) then we can make trivial changes to make it CountLines.
I am NaN ;)

shekel

Thats truth...  in my file the procedure is called 'ReadIpFile' because i save few ips in that file but when i posted i decided delete the 'ip' part.
In my language 'size' is 'tamaƱo'

rrr314159

Huh! That's pretty convincing!

Now if you could make the necessary changes, and just call the routine from a start: label (takes a few lines), post the results, we'll have something very easily modifiable to Count Lines
I am NaN ;)

shekel

Its better way?


start:
  invoke CountLinesIpFile
  --> eax = num of lines
  invoke ReadIpFile, 3
  --> esi = have text of line number 3
  --> if not have this line esi = {empty}
--------

CountLinesIpFile proc

invoke ReadIpFile, -1
inc eax
ret

CountLinesIpFile endp


ReadIpFile proc Linea:DWORD
LOCAL szFile[MAX_PATH]:DWORD
LOCAL hRead:HANDLE
LOCAL hMemory:HANDLE
LOCAL pMemory :DWORD                             
LOCAL SizeReadWrite :DWORD     
LOCAL tamano: DWORD             
LOCAL LineaActual:DWORD   
 
invoke lstrcpy, addr szFile, chr$("C:\file.txt")

invoke CreateFile, addr szFile,GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
mov hRead, eax
invoke GetFileSize, hRead, NULL
mov tamano, eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT, addr tamano
    mov  hMemory,eax
    invoke GlobalLock,hMemory
    mov  pMemory,eax 
invoke ReadFile, hRead, pMemory, addr tamano , addr SizeReadWrite, 0

invoke lstrlen, pMemory
mov ecx, eax
mov esi, pMemory 
xor edx, edx
letra:
mov al, [esi]
.if al == 0Dh
inc esi
mov al, [esi]
.if al == 0Ah 
inc edx
mov bx, 0
mov [esi-1], bx
.endif
.endif
inc esi
loop letra

mov eax, [Linea]
.if eax == -1
push edx
invoke GlobalUnlock, hMemory
invoke GlobalFree, hMemory
invoke CloseHandle, hRead
pop eax
ret
.endif
dec eax
.if eax > edx
xor esi, esi
ret
.endif

mov [LineaActual], 1
mov esi, pMemory
mov ecx, edx
linea:
mov eax, [LineaActual]
.if [Linea] == eax
mov ecx, 1
.else
invoke lstrlen, esi
add esi, eax
add esi, 2h
inc [LineaActual]
.endif
loop linea




invoke MessageBox, NULL, esi, chr$("aa"), MB_OK


invoke GlobalUnlock, hMemory
invoke GlobalFree, hMemory
invoke CloseHandle, hRead

ret

ReadIpFile endp

shekel

A simple question...

If i push a reg inside a procedure and 'forget' recover this value with pop its bad for my application ??

rrr314159

Hmmm ... do you have MASM32? How do you run your code? This still won't work, of course. IF you're using masm32, you need at least these lines at the top:

include \masm32\include\masm32rt.inc

CountLinesIpFile proto
ReadIpFile proto :DWORD

.code


And then, keep going and get it to run (error messages will make it clear what's needed). Once it's running it's trivial to make it Count Lines .. but until it runs, can't do anything with it

While I was typing you asked:

Quote from: shekelIf i push a reg inside a procedure and 'forget' recover this value with pop its bad for my application ??

- Sure is, it will crash (go off into deep space, as we say)
I am NaN ;)

dedndave

if you leave the stack unbalanced, all sorts of bad things happen
eventually, you will get some sort of exception (program crash)
probably sooner than later - lol

here is a simple example of how to call a function with INVOKE
;###############################################################################################

        INCLUDE    \Masm32\Include\Masm32rt.inc

;###############################################################################################

MyFunc PROTO :DWORD,:DWORD

;###############################################################################################

        .DATA

szMyString db 'Hello World!',13,10,0

;***********************************************************************************************

;       .DATA?

;###############################################################################################

        .CODE

;***********************************************************************************************

main    PROC

        INVOKE  MyFunc,offset szMyString,3

        print   chr$(13,10)
        inkey
        INVOKE  ExitProcess,0

main    ENDP

;***********************************************************************************************

MyFunc  PROC USES EBX ESI lpString:DWORD,nCount:DWORD

    mov     ebx,nCount
    mov     esi,lpString
    .if ebx
        .repeat
            print   esi
            dec     ebx
        .until ZERO?
    .endif
    ret

MyFunc  ENDP

;###############################################################################################

        END     main

Farabi

Hi, when a program hit "ret" instruction, the address it point is the last one on the stack frame. So, if you forget to pop, it will execute a wrong address.



Push addr MyProcedure
ret

MyProcedure proc


ret
MyProcedure endp


That code will jump to myprocedure and start the termination by returning it to the first caller, the OS.
http://farabidatacenter.url.ph/MySoftware/
My 3D Game Engine Demo.

Contact me at Whatsapp: 6283818314165

jj2007

Quote from: shekel on May 23, 2015, 03:26:47 PMIf i push a reg inside a procedure and 'forget' recover this value with pop its bad for my application ??

Yes and no 8)

include \masm32\include\masm32rt.inc

.code
MyProcedure proc somearg
  push eax
  push ecx
  push edx
  print somearg ; use Console build
  ret
MyProcedure endp

start: invoke MyProcedure, chr$("See the text?")
MsgBox 0, "Hello World", "It works:", MB_OK
exit
end start


Build it a) with standard Masm, b) with JWasm, then launch Olly for both and see why they behave differently.
In any case, you should balance the stack.

rrr314159

@jj2007,

I'll be darned. I guess u can't call it a bug, though? After all,

Quote from: jj2007In any case, you should balance the stack.

does anyone else in the world know this obscure little difference ... ? even Japheth and Habran might not

good catch :t
I am NaN ;)

jj2007

Japheth and a few others (Dave, qWord, Hutch, Habran, ...) surely know it.
A bug? No. Masm is too tolerant, maybe.

nidud

#12
deleted

rrr314159

Obviously you're right a lot of thought was put into JWasm! But only timing is examined here, no explicit mention of fact that if stack is unbalanced in a proc that's OK in MASM not JWasm; only locals on the stack were considered.

It's not completely ridiculous to allow unbalanced stack in a proc ... in fact that's sort of what a stack frame w/ locals is. May be "too tolerant", not clear.

Unfortunately it doesn't help the cause when asking people to switch to JWasm: legal ML code can explode! Wonder how many of these little "gotchas" there are? And imagine chasing down a bug like that in a prog with thousands of lines - they'd definitely go back to ML
I am NaN ;)

nidud

#14
deleted