flat assembler
Message board for the users of flat assembler.

Index > Windows > How to make void functions?

Author
Thread Post new topic Reply to topic
rohagymeg



Joined: 19 Aug 2011
Posts: 77
rohagymeg 06 Jan 2012, 17:49
I'm gonna call ReadFile with the same parameters at least 100 times and don't know how to make it a function with no input parameters. What's the best way to do this? Proc didn't work for me. Thanks!
Code:
invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0
cmp [buffer], "T"
jne exit

invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0
cmp [buffer], "E"
jne exit

invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0
cmp [buffer], "S"
jne exit

invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0
cmp [buffer], "T"
jne exit

;further code
    
Post 06 Jan 2012, 17:49
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 06 Jan 2012, 18:00
I think this should work:
Code:
invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0 
cmp [buffer], "T" 
jne exit 

sub esp,(5 * 4)

invoke ReadFile; [hFile], buffer, 1, no_bytes_read, 0 
cmp [buffer], "E" 
jne exit

; ...    
Assuming ReadFile doesn't trash the parameters.
Post 06 Jan 2012, 18:00
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jan 2012, 18:29
rohagymeg: for this particular use, please do a full buffer read and then do an in-memory scan - it's going to be a lot less code, and ReadFile calls are pretty expensive.

cod3b453: very bad idea when interfacing with external code - you have no guarantee that even if it works now, it won't be broken for some previous or up-and-coming version of the external code. But for internal code which you have full control of, this is one of those optimizations that's sweet and "yeah, I'm an assembly coder" like Smile

As an exercise in how to save a few code bytes, a quick-and-naïve idea would be:

Code:
proc ReadAndTest test_value
       invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0
       mov             al, [test_value]
    cmp             [buffer], al
        ret
endp

;....... stuff....
invoke ReadAndTest, "T"
jne               exit
invoke  ReadAndTest, "E"
jne               exit
invoke  ReadAndTest, "S"
jne               exit
invoke  ReadAndTest, "T"
jne               exit
    


...not the approach I'd use, though, since as I mentioned above calls to ReadFile are expensive... and each invocation of ReadAndTest are 7 bytes at the call site. Furthermore, this approach requires global variables for hFile, buffer and no_bytes_read, where I generally prefer locals.

_________________
Image - carpe noctem
Post 06 Jan 2012, 18:29
View user's profile Send private message Visit poster's website Reply with quote
rohagymeg



Joined: 19 Aug 2011
Posts: 77
rohagymeg 06 Jan 2012, 18:35
Thanks! I wanted to read into buffer line by line, but I don't know how to do it in a formal way. Is there a search function for finding the position of 0xD, 0xA (new line)
Post 06 Jan 2012, 18:35
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 06 Jan 2012, 18:36
Although cod3b453 probably works, ReadFile is technically allowed to trash the parameters so perhaps you could just use a loop?
Code:
pattern db "TEST"
.
.
.
mov ebx, -4
mov edi, pattern + 4
.read:
invoke ReadFile, [hFile], buffer, 1, no_bytes_read, 0 
mov al, [buffer]
cmp al, [edi+ebx]
jne exit
inc ebx
jnz .read    
Post 06 Jan 2012, 18:36
View user's profile Send private message Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 6115
Location: Poland
MHajduk 06 Jan 2012, 18:40
f0dder wrote:
...not the approach I'd use, though, since as I mentioned above calls to ReadFile are expensive... and each invocation of ReadAndTest are 7 bytes at the call site. Furthermore, this approach requires global variables for hFile, buffer and no_bytes_read, where I generally prefer locals.
Wouldn't be better in this case to read the entire block of data from a file and then read single bytes (from memory) using 'lodsb' instruction?

I guess that rohagymeg wants to make something like a text parser, am I right?
Post 06 Jan 2012, 18:40
View user's profile Send private message Visit poster's website Reply with quote
rohagymeg



Joined: 19 Aug 2011
Posts: 77
rohagymeg 06 Jan 2012, 18:43
I made a config.txt parser in c++. I'm remaking it in FASM. My big problem is how do I deal with ReadFile instead of GetLine.
Post 06 Jan 2012, 18:43
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz 06 Jan 2012, 18:45
Try something like this:
Code:
proc someproc
pushad
some functions here
popad
ret
endp    

This function will return nothing, thus will not destroy anything Smile
Post 06 Jan 2012, 18:45
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jan 2012, 18:47
rohagymeg wrote:
Thanks! I wanted to read into buffer line by line, but I don't know how to do it in a formal way. Is there a search function for finding the position of 0xD, 0xA (new line)
Ah, line-based data.

There's several ways to handle this, depending on your needs Smile

If you're dealing with 'sane' file sizes, you can either memory-map the file or read the entire file to memory - then you've got one big buffer you can do line-parsing in.

If you need to deal with really huge input data, or you need your application to play nice if run under a Terminal Services machine, you'll want to process in chunks.

I see you mention C++ - you're probably used to iostreams of fgetc. Both iostream and the FILE functions have their own internal buffering so they avoid calling ReadFile all the time. [url]This link[/url] has some stats that show why you don't want to call ReadFile repeatedly with small read sizes Smile

Building your own generic buffered file I/O isn't a trivial programming exercise, but not rocket science either - could be worth it for the learning experience. If you just need to parse smallish files without a lot of effort, I'd say read it into a buffer and parse it there.

_________________
Image - carpe noctem
Post 06 Jan 2012, 18:47
View user's profile Send private message Visit poster's website Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 6115
Location: Poland
MHajduk 06 Jan 2012, 18:49
rohagymeg wrote:
I made a config.txt parser in c++. I'm remaking it in FASM. My big problem is how do I deal with ReadFile instead of GetLine.
So definitely the best solution is to read bigger "chunks" of data from the file (using ReadFile with proper parameters) to the specified buffers and then analyse text with 'lods*' instructions. In this case you can manipulate position pointer in the text by increase/decrease of the esi register value - for example, you can "unget" chars easily. Operations on the data stored in memory are generally faster than those performed on the files.
Post 06 Jan 2012, 18:49
View user's profile Send private message Visit poster's website Reply with quote
rohagymeg



Joined: 19 Aug 2011
Posts: 77
rohagymeg 06 Jan 2012, 18:53
Thanks for the input people! This seems disgusting but that's how windows handles things Smile
Post 06 Jan 2012, 18:53
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jan 2012, 19:05
rohagymeg wrote:
Thanks for the input people! This seems disgusting but that's how windows handles things Smile
Not just Windows - if you look at a *u*x libc they'll also be doing buffering ontop of the read system calls. The system calls need to do user->kernel->usermode transitions (which are expensive!) and a lot of checks in order to keep filesystem cache coherent across all processes accessing the same file. This is a rather large amount of overhead, so you need to do in-application buffering if you don't want sluggish performance.

_________________
Image - carpe noctem
Post 06 Jan 2012, 19:05
View user's profile Send private message Visit poster's website Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 06 Jan 2012, 20:38
f0dder wrote:
...
cod3b453: very bad idea when interfacing with external code - you have no guarantee that even if it works now, it won't be broken for some previous or up-and-coming version of the external code. But for internal code which you have full control of, this is one of those optimizations that's sweet and "yeah, I'm an assembly coder" like Smile
...
Very Happy yeah, the buffered method is better for this.
Post 06 Jan 2012, 20:38
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jan 2012, 22:20
cod3b453 wrote:
f0dder wrote:
...
cod3b453: very bad idea when interfacing with external code - you have no guarantee that even if it works now, it won't be broken for some previous or up-and-coming version of the external code. But for internal code which you have full control of, this is one of those optimizations that's sweet and "yeah, I'm an assembly coder" like Smile
...
Very Happy yeah, the buffered method is better for this.
But please DO keep the "stack re-use" method in mind when you surely do own the stack - it can be pretty sweet Smile - just be sure to keep the disclaimers and not recommend it where it's not applicable Smile

_________________
Image - carpe noctem
Post 06 Jan 2012, 22:20
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.