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
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.
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'
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
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
A simple question...
If i push a reg inside a procedure and 'forget' recover this value with pop its bad for my application ??
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)
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
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.
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.
@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
Japheth and a few others (Dave, qWord, Hutch, Habran, ...) surely know it.
A bug? No. Masm is too tolerant, maybe.
deleted
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
deleted
Quote from: rrr314159 on May 29, 2015, 02:57:44 AMUnfortunately 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
Going back to ML is not a good option; an unbalanced stack means the coder has lost control (unless he did it on purpose). Worst case is
someproc uses esi edi ebx arg1, arg2 - you are trying to preserve non-volatile regs but you are getting back garbage - and it may take a long time until that actually produces a fat problem, usually on the client's premises :icon_mrgreen:
P.S.: Gotchas (http://web.archive.org/web/20140202233143/http://www.japheth.de/JWasm/Manual.html#CHAPMASMBUGS)
Of course the coder may have done it on purpose. In fact I do something like this in my "invoke macros". There I'm explicitly "leave"ing but if I'd known this about ML, I might conceivably have used their proc. If so, then years later I tried to switch to JWasm and it blew up ... I'm thinking of a case like that, where somebody tries his large ML prog under JWasm (because, for instance somebody like me recommends it) and it blows up for this reason. He's not going to want to chase that down (he did it years ago, and doesn't even know what the problem is anyway).
It occurs to me that one of the switches -Zm, -Zne, -Zv8 might force compatibility on this issue, don't have time to check it. But I'd say this is the sort of thing one of those switches should do: restore the (presumably) inferior ML way if coder wants it.
Some of those "gotchas" u link to are in fact gotchas, not all. Whenever a "problem" is "fixed" such that the improved JWasm won't run the old code, that's a gotcha. Again, that's (I bet) what those Z switches are for.
BTW .. there's 2 d**n much religion on this board! There's the liberal religion, the MACRO religion, atheism religion, Bertrand Russell religion, C/C++ religion ... pls don't start with the JWasm religion too! It's a great prog, best in the world, all other progs should not even be called prog's by comparison; Oh great J, mother of all perfection ... :biggrin:
Quote from: rrr314159 on May 29, 2015, 04:15:40 AMpls don't start with the JWasm religion too! It's a great prog, best in the world, all other progs should not even be called prog's by comparison; Oh great J, mother of all perfection ... :biggrin:
It's difficult to ignore it. While ML 6.14 is supplied with Masm32, it is too outdated for serious use. Higher versions are difficult to find and/or to install, and then there is always the license issue.
Today I found a new incompatibility between ML and J, in my ternary operator function macro. The fix will be online soon. It has become much better over time, but I still need fixes for this kind of problem. Nowadays J has become easier to use than ML, but still, I make sure that all MB macros must work with ML 6.15 ... 10 and JWasm.