The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: agnokapathetic on April 12, 2006, 08:06:16 PM

Title: Reading a file.
Post by: agnokapathetic on April 12, 2006, 08:06:16 PM
Hey all,
I'm just starting to take up assembly as a hobby after working with higher level languages such as Python and Java for years. As i devel into Assembly it seems quite elegant in its extreme, raw, simplicity.

Anyways, with my first project, I'm trying to read a file, and use the user32 MessageBox to display the information.

Im thinking my problem might be a type mistmatch (If you have them in Assembler, Like I said i'm and infant in this language).


.486
.model flat, stdcall
option casemap:none


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

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

.data
logfile db "test.log",0
.data?
hLog HANDLE ?                                  ; File handle
temp_buffer   db 32768 dup(?)

SizeReadWrite DWORD ?                   ; number of bytes actually read or write
.code
start:
invoke CreateFile,ADDR logfile, GENERIC_READ ,  FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,   NULL
mov hLog,eax

invoke ReadFile,hLog,temp_buffer, 16, ADDR SizeReadWrite,NULL ; Size hardcoded

invoke MessageBox,0,temp_buffer ,"Test",0

invoke CloseHandle,hLog

end start


Thanks in advance,
--Joel
Title: Re: Reading a file.
Post by: Mark Jones on April 12, 2006, 08:56:39 PM
Hello Joel, welcome to the group. :toothy

Code looks pretty good, have you tried running it in a debugger such as OllyDbg (http://www.ollydbg.de/) yet? CreateFile and ReadFile are very particular about their flags and permissions. Stepping through each instruction (F8 in Olly) can "show" you what happens on nearly a line-by-line basis - very helpful for isolating issues.

There might be a few caveats with the program as it is written (I can't test it at the moment.) One is that the MessageBox API will only display a set quantity of text. If you try to display more than it can hold (about 1k probably), it will just exit with an (unhandled) error.

There are a few errors in the line

    invoke MessageBox,0,temp_buffer ,"Test",0


If you look up the MessageBox API at MSDN or in the Win32.HLP file, it shows the string parameters as "lpText" and "lpCaption." The lp basically stands for pointer, so that token should be a pointer and not a value, so try ADDR temp_buffer.

Quotations are not allowed in INVOKE statements. You can try replacing INVOKE with FN, which is a macro like invoke which allows quotations. That might do the trick. You'll need to include \masm32\macros\macros.asm

Finally you might want to consider allocating large buffers dynamically using routines like masm32's STRALLOC and STRFREE or Windows' GlobalAlloc and related. The .data? section is intended primarily for global uninitialized variables, not large buffers (it should work either way though.) Have fun!  :U
Title: Re: Reading a file.
Post by: MichaelW on April 12, 2006, 09:08:45 PM
Also, you need to properly end the process, normally done with a call to ExitProcess.

If the Message Box caption "Error" is acceptable you can pass NULL in the lpCaption parameter.

Title: Re: Reading a file.
Post by: zcoder on April 13, 2006, 12:03:35 AM
Try to change these lines to this:

   invoke ReadFile,hLog,addr temp_buffer, 16, ADDR SizeReadWrite,NULL ; Size hardcoded
   
   invoke MessageBox,0,addr temp_buffer ,"Test",0   

I am not sure what macro you are using for the "Test" but if your not that is wrong too.

Zcoder....
Title: Re: Reading a file.
Post by: hutch-- on April 13, 2006, 10:53:54 AM
Joel,

Welcome on board. Here is a quick fix that works.


.486
.model flat, stdcall
option casemap:none


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

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

  .data
    logfile db "test.log",0
    msgbox_title db "Test",0

  .data?
    hLog HANDLE ?                                  ; File handle
    temp_buffer   db 32768 dup(?)
    fsiz dd ?
    SizeReadWrite DWORD ?                   ; number of bytes actually read or write

.code
start:

    invoke CreateFile,ADDR logfile,GENERIC_READ,
           FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
    mov hLog,eax

    invoke GetFileSize,hLog,NULL
    mov fsiz, eax

    invoke ReadFile,hLog,ADDR temp_buffer,fsiz, ADDR SizeReadWrite,NULL

    invoke MessageBox,0,ADDR temp_buffer,ADDR msgbox_title,0

    invoke CloseHandle,hLog

    invoke ExitProcess,0

end start


See extra version below.
Title: Re: Reading a file.
Post by: The Svin on April 13, 2006, 11:27:33 AM
It also good to use GetFileAttributes before CreateFile, since there is possibilities that attributes you assumed for the file wouldn't match the factual ones.
Title: Re: Reading a file.
Post by: agnokapathetic on April 14, 2006, 04:59:08 AM
Thanks to all of you.

I think I'm still treating the lanuage like i'de treat a higher level language, and i need to start thinking outside of my abstracted box  :lol

Thank you yet again, you all are part of a very welcoming community.

--Joel
Title: Re: Reading a file.
Post by: PBrennick on April 14, 2006, 09:53:46 PM
Hutch,
The second example you post, the one that will open any size file will not assemble.  He will not be able to assemble it because temp_buffer is missing.

Paul
Title: Re: Reading a file.
Post by: hutch-- on April 14, 2006, 10:15:02 PM
Thanks Paul,

I appear to have resaved a version that was only partly modified. I get caught that way occasionally with multiple copies of the same source.

here is the fix.


    .486
    .model flat, stdcall
    option casemap:none


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

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

    .data
      logfile db "test.log",0
      msgbox_title db "Test",0

    .code

; --------------------------------------------------

start:
    call main
    invoke ExitProcess,0

; --------------------------------------------------

main proc

    LOCAL hLog  :DWORD      ; file handle
    LOCAL fsiz  :DWORD      ; file size
    LOCAL bwrt  :DWORD      ; bytes written
    LOCAL hMem  :DWORD      ; memory handle

    invoke CreateFile,ADDR logfile,GENERIC_READ,
           FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
    mov hLog, eax

    invoke GetFileSize,hLog,NULL            ; get the file size
    mov fsiz, eax
    sub fsiz, 1

    invoke GlobalAlloc,GMEM_FIXED,fsiz      ; allocate at least that much memory
    mov hMem, eax

    invoke ReadFile,hLog,hMem,fsiz,ADDR bwrt,NULL

    invoke MessageBox,0,hMem,ADDR msgbox_title,0

    invoke CloseHandle,hLog                 ; close the file handle

    invoke GlobalFree,hMem                  ; free the allocated memory

    ret

main endp

; --------------------------------------------------

end start
Title: Re: Reading a file.
Post by: PBrennick on April 14, 2006, 10:30:32 PM
That definitely works, but have you tried it with a large file?   It is not very usuable without scrollbars!

Paul
Title: Re: Reading a file.
Post by: hutch-- on April 14, 2006, 10:32:40 PM
 :bg

You are right, a MessageBox is not suited for large text display but i did not want to change the original example too much or make it too complicated.