The MASM Forum

General => The Campus => Topic started by: moha1 on April 12, 2014, 06:37:22 AM

Title: read from binary file
Post by: moha1 on April 12, 2014, 06:37:22 AM
Hi guys,
I have a project to do in wich i must use a variable(byte) which is in a binary file so I must read for example the first byte or any byte depending on the port i want to read from,how should I do this?


Thanks

Title: Re: read from binary file
Post by: dedndave on April 12, 2014, 07:31:49 AM
use CreateFile to open the file
use SetFilePointer or SetFilePointerEx to set the file pointer
use ReadFile to read the byte into a buffer
use CloseHandle to close the file handle

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365541%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365541%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365542%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365542%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx)

use the forum search tool for examples of each function
or - use Windows Explorer search tool to look in masm32\examples for files containing those function names
Title: Re: read from binary file
Post by: dedndave on April 12, 2014, 07:33:36 AM
if you like, you can do it without setting the file pointer
make the buffer large enough to read the entire file up to the desired byte
then access the buffer at the desired offset
Title: Re: read from binary file
Post by: moha1 on April 12, 2014, 07:43:07 AM
I ve found the fileio example from masm32 but it doesn't t help me because it reads from a text file and not from a binary file in which I have a number of ports and each port is represented by a byte.I must get the byte that is in port 0 that means the first byte and put it into a variable in my program.
Title: Re: read from binary file
Post by: KeepingRealBusy on April 12, 2014, 08:13:49 AM
In MASM it doesn't matter what the underlying format is, you always read BYTES. You can then determine what to do with that BYTE data. In your case, just read and use the first BYTE.

Dave.
Title: Re: read from binary file
Post by: jj2007 on April 12, 2014, 10:08:17 AM
Here is a complete example that reads one byte from a known file. We expect that byte to be "M" (Ascii 77) as in "MZ" ;-)

include \masm32\include\masm32rt.inc

.code
start:
  ; open a file - the handle returned in eax gets pushed on the stack:
  push fopen("\Masm32\examples\exampl05\hlldemo\fileio\fileio.exe")
  push 0      ; create an empty 4-byte buffer on the stack
  mov ecx, esp      ; and store its address to ecx
  push eax            ; create another 4-byte buffer on the stack
  mov edx, esp      ; and store its address to edx
  invoke ReadFile, eax, ecx, 1, edx, 0      ; invoke ReadFile, handle, pBuffer, #bytes, pBytesRead, 0
  .if !eax
      print LastError$(), 13, 10      ; good to know if an error occurred
  .endif
  pop ecx                  ; get value from the second stack buffer
  print str$(ecx), " bytes read", 13, 10
  pop ebx                  ; get value from the first stack buffer
  call CloseHandle      ; the handle is still on the stack, so this is invoke CloseHandle, eax
  print str$(ebx), " is the first byte"
  exit

end start


MasmBasic version:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=FileRead$("\Masm32\examples\exampl05\hlldemo\fileio\fileio.exe")
  Inkey "The first two bytes are [", Chr$(Cvi (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1023)(esi)), "]"
  Exit
end start


Output: The first two bytes are [MZ]
Title: Re: read from binary file
Post by: dedndave on April 12, 2014, 11:23:45 AM
here's another example
notice that i set the file pointer to 0
that is not a necessary step, as when you open a file, it is set to 0
but - if you want to read some other offset, the code is there
Title: Re: read from binary file
Post by: moha1 on April 12, 2014, 06:55:14 PM
Thank's a lot guys:D
Title: Re: read from binary file
Post by: dedndave on April 13, 2014, 12:16:04 AM
i wanted to mention....

the buffer only needs to be 1 byte long, in this case
i modified a program that i had previously written to create emu8086Read
it read the entire contents of the file into the buffer
Title: Re: read from binary file
Post by: moha1 on April 13, 2014, 09:26:49 AM
I've tried to make what you have said in my code and it doesn't work,it works well separate reading from emu8086.io.
So i have a fan wich i must controll from emu8086 so i must write from emu in emu8086.io file and i must take the value and controll my fan.
The variable i must modify is named Buffer wich inittialy i defined 5 to show that the code works.
I've created a proc wich can read from file and when i'm calling it before i do things with my buffer variable,my fan image won't apear.
I have no ideea why it is doing like that because separate,the two programs works perfectly.
So i have commented the part where i have done the file reading proc and where i call it.
So al i must do is to read from emu8086.io and put the value in buffer variable.

Any ideeas?

Thanks in advance
Title: Re: read from binary file
Post by: dedndave on April 13, 2014, 10:20:51 AM
i don't think you really want to open, read, close the file every 30 mS   :icon_eek:
that's a little over 30 times per second
Title: Re: read from binary file
Post by: dedndave on April 13, 2014, 10:26:39 AM
you could also have the "file" routine return an error condition
and - i would choose a more unique name for it   :P
GetFileByte proc

;--------------------------------
;get file size
;--------------------------------

        INVOKE  GetFileAttr,offset szFileName
        or      eax,eax
        jz      Exit00

        mov     dwFileSize,eax

;--------------------------------
;open file
;--------------------------------

        INVOKE  OpnFile,offset szFileName,OPF_FILERANDOM
        sub     eax,INVALID_HANDLE_VALUE
        jz      Exit00

        add     eax,INVALID_HANDLE_VALUE
        mov     hFile,eax

;--------------------------------
;set file pointer (to 0)
;--------------------------------

        INVOKE  SetFilePointer,hFile,0,NULL,FILE_BEGIN

;--------------------------------
;read 1 byte into buffer
;--------------------------------

        INVOKE  ReadFile,hFile,offset Buffer,1,offset dwNumBytes,NULL

;--------------------------------
;close file
;--------------------------------

         INVOKE  CloseHandle,hFile

Exit00:   
ret


GetFileByte endp

if the routine exits with EAX = 0, it means an error occured
Title: Re: read from binary file
Post by: moha1 on April 13, 2014, 06:14:45 PM
I have done what you have said,i have modified the routine,it doesn't give me any error regarding eax.
The only problem is when i call the proc,the image dissapears.I don't have any errors.
I also tryied pushing eax,abx,acx because they are used after but it still doesn't work,need help!
Thanks
Title: Re: read from binary file
Post by: dedndave on April 13, 2014, 08:39:30 PM
here's the question...

how often is the value in the file going to change ?

you are trying to read it 33 times per second
if you can read it once - then do that outside of the WM_TIMER code (WM_CREATE, perhaps)

if the file value is updated often, then you might take another approach
set up a counter (dword) variable (initial value = 1)
each time WM_TIMER is received, decrement the counter
when the counter reaches 0, read the file byte and reset the counter variable
now, how often it is updated depends on the timer elapse and the counter variable
i would think you could update once every minute or so
so, the counter variable might be reset to something like 2000
Title: Re: read from binary file
Post by: moha1 on April 13, 2014, 09:15:05 PM
The value is changed often beause i controll the fan from emu 8086 so i can change the value after 2 seconds for example.
The thing is i'm knew in masm and i don't know how to work with a counter.
Can you help me please:)
Title: Re: read from binary file
Post by: moha1 on April 13, 2014, 09:16:19 PM
I've also tried to only read it once,outside the counter and it hasn't worked
Title: Re: read from binary file
Post by: dedndave on April 14, 2014, 12:19:29 AM
well - the value at offset 0 in your emu8086.io file is 0, if that tells you anything   :P
i have another emu8086.io file here that is 201 bytes in size, and has 0C2h in the first byte

in the .DATA section
dwFileCounter dd 1
the first time WM_TIMER is received, it will cause an initial file read because 1 will become 0

in the WM_TIMER code
    dec     dwFileCounter
    .if ZERO?
        mov     dwFileCounter,2000  ;with a 30 mS timer elapse, update once every minute
        call    GetFileByte
        .if !eax
            INVOKE  Beep,800,100    ;beep at 800 Hz for 100 mS if error reading file
        .endif
    .endif
Title: Re: read from binary file
Post by: dedndave on April 14, 2014, 12:25:58 AM
i updated the GetFileByte routine previously posted
these are the lines that changed
        sub     eax,INVALID_HANDLE_VALUE
        jz      Exit00

        add     eax,INVALID_HANDLE_VALUE
        mov     hFile,eax
Title: Re: read from binary file
Post by: jj2007 on April 14, 2014, 12:49:10 AM
Wasteful, Dave :eusa_naughty:

if INVALID_HANDLE_VALUE eq -1
   inc eax
   jz Exit00   ; 4 bytes

   dec eax
  else
   sub eax, INVALID_HANDLE_VALUE
   jz Exit00   ; 8 bytes

   add eax, INVALID_HANDLE_VALUE
  endif
Title: Re: read from binary file
Post by: moha1 on April 14, 2014, 01:34:42 AM
I've done all you have said and made all the necesary changes that you told me,but when we put the call proc ,my image dissapears:(.
It's the same problem.There are no errors but if i let the call getfilebyte there my image won't apear.I'm stuck:(
Here is my program with the updates.In also modifyed my emu 8086 file,and the number at the first port is 155 now.
I don't have any ideeas what the problem can be:(
Title: Re: read from binary file
Post by: MichaelW on April 14, 2014, 03:08:39 AM
In my test, using your files, the problem was not the calls to GetFileByte but an endless loop in your WM_TIMER handler. Try enabling the calls to GetFileByte and commenting out the "jne et". I suggest you clean up your logic and your code. Before you go to the trouble of using a debugger to find the problem, you could try linking your app as a console app and adding code to display whatever you need to see on the console. I prefer to use the printf macro for this, for example:

    CALL GetFileByte
    pushad
    printf("EAX:%d\n",eax)
    popad


    mov al,byte ptr Buffer
    pushad
    ; printf expects 32 or 64-bit integers:
    movzx eax, al
    printf("AL:%d\n",eax)
    popad

    add com,1
    pushad
    movzx eax, com
    printf("com:%d\n",eax)
    popad


EAX:1
AL:155
com:2



Title: Re: read from binary file
Post by: dedndave on April 14, 2014, 03:21:01 AM
also - you can speed up the GetFileByte process......

open the file in WM_CREATE code and store the handle
i like to use GetFileAttr to get the file size and verify the file exists - optional
if there is an error, MessageBox and exit with EAX = -1 to exit without creating the window

in the WM_TIMER code, SetFilePointer to 0 and use ReadFile to read 1 byte

in the WM_DESTROY handler, INVOKE CloseHandle,hFile
Title: Re: read from binary file
Post by: moha1 on April 14, 2014, 07:03:21 AM
You were right,it worked because i used a while loop instead of comparing and jumping to et label.
The thing is that i don't understand why with jne doesn't work and with a while loop it worked?
I must mention that using both methods,the fan was doing exactly the same thing,but when the getfilebyte was called,with jne not commented my image was disapearing and when i used while loop,with the same code it worked.
I was only comparing com variable with al,a register in wich i put the buffer vaiable.I did this thing because cmp does not allow memory,memory,it can allow memory,registerso i've put it in al.
Then i was adding using FPU the number of times it was in Buffer,that was read from the file.
With the while loop i've done the same thing but i havn't used any jump,can you tell me why it happened like this?

THANKS
Title: Re: read from binary file
Post by: MichaelW on April 14, 2014, 10:22:31 AM
To know what is happening in the loop you need some way to monitor the values of the loop variables. By displaying the values of AL and com inside the loop I can see that the loop is running 155 times each time the timer fires with the call to GetFileByte enabled, and 7 times with the call to GetFileByte disabled. On each loop the value in xmm3 is being doubled. If I change the code to add 1.0 to the value in xmm3 on each loop, instead of doubling it:

      add com,1
      ;addss xmm3,xmm3
      .data
          xxx REAL4 1.0
      .code
      addss xmm3,xxx


Then the fan displays OK with the call to GetFileByte enabled.
Title: Re: read from binary file
Post by: moha1 on April 14, 2014, 05:34:32 PM
It is OK because I have defined my buffer at the begginig being 7 but the thing in using cmp com,al and jmp makes my image to disappear,obviously it s an endless loop but the code is the same when I m doing it with while and works , I m just doing while com<al and then the code is the same and I don't understantand why because my cmp , jump is making the same thing that while loop does
Title: Re: read from binary file
Post by: KeepingRealBusy on April 15, 2014, 01:57:32 AM
Knowing nothing about the code, but just reading the descriptions of the problem you have (works if using while but not with cmp jxx), I can only assume that your cmp jmp code is interpreting the results incorrectly, i.e., you are making a signed comparison and jumping on an assumed  unsigned result, or  you are making an unsigned comparison and jumping on an assumed  signed result. Read the documentation about ja (jump if above - unsigned) and jg (jump if greater - signed).

Dave.
Title: Re: read from binary file
Post by: FORTRANS on April 15, 2014, 04:39:04 AM
Hi,

   As Dave says, you may have a wrong conditional jump.  Put
.XLIST before including the INCLUDE files.  And put a .LIST directive
after the include files, and generate a listing of both programs so
you can see what changes in teh generated code.  You can put
the .XLIST and .LIST just around the code in question, if you think
that is easier.

Regards,

Steve N.