The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Rainstorm on April 09, 2007, 11:50:49 PM

Title: What's wrong with this code
Post by: Rainstorm on April 09, 2007, 11:50:49 PM
Hi,
This code is assembling proper & running but it isn't functioning as expected.
Its supposed to display the highest no of charactesr (that a line has). but its displaying 0
something wrong's happening after the  cmp byte ptr [esi], 0 line & it seems to be
jumping to exit.

   .data

   fpattern db "*.txt",0
    hfile   dd  0
    pfbuff  dd  0
    flen    dd  0
    fname   db  "H:\Project\filetest.txt",0
    count1 dd 0
;----------------------------------------------------------------------

    .code

start:

;---------------
; load file into a buffer
;----------------

  invoke read_disk_file,addr fname,addr pfbuff, addr flen 
  cmp eax, 0
  jne @F

  print "file open error",13,10
  inkey
  exit

@@:
    xor esi, esi
    mov esi, pfbuff       ; move the address into esi
    jmp count_
   
  pre_count:
      xor ecx, ecx
      add esi, 1
   
  count_:
      cmp byte ptr [esi], 0            ; check for end of file
      je exit_
      cmp byte ptr [esi], 10          ; check for end of line
      je reset_count
      add ecx, 1                        ; keep count of characters in ecx
      add esi, 1
      jmp count_
; --------------------------------------------------------
; replace the value in count1 with ecx if it is less than the value in ecx
;----------------------------------------------------------
   reset_count:
      cmp ecx , count1
      jna pre_count
      mov count1, ecx
      jmp pre_count

;--------------------
; display the results
;--------------------

exit_:
    free pfbuff
    print "highest character count: - "
    print ustr$(count1),13,10
    inkey
    exit

end start
Title: Re: What's wrong with this code
Post by: Jimg on April 10, 2007, 12:59:20 AM
I had not looked at it before, but the read_disk_file proc seems to have several points of possible failure that is not passed to the user.  Perhaps it would be better to handle the reading yourself to see what's going wrong.     It's not that hard to do a getfilesize, followed by a heapalloc and a readfile.  Or perhaps in your case better to do a CreateFileMapping, and MapViewOfFile.
Title: Re: What's wrong with this code
Post by: Rainstorm on April 10, 2007, 01:38:38 AM
Jimg
appreciate the feed back.

i had inserted some code (not in the above post) just to test what was going wrong.
the first value in esi returns the right letter,  like is in the file but it somehow doesn't go pasthe je exit line here count_:
      cmp byte ptr [esi], 0            ; check for end of file
      je exit

seems kinda contradictory.
Title: Re: What's wrong with this code
Post by: dsouza123 on April 10, 2007, 01:44:07 AM
[code
   xor esi, esi
   mov esi, pfbuff       ; move the address into esi
   xor ecx, ecx          ; need this or the first line could prestart with a large amount
   jmp count_



  reset_count:
     add ecx, 1                        ; add this so cr and lf are both counted
     cmp ecx , count1
Title: Re: What's wrong with this code
Post by: Jimg on April 10, 2007, 02:42:53 AM
How about posting a file with some actual working code?  Trying to assemble your code as you posted it was a problem.
This code:jne @F

  print "file open error",13,10
  inkey
  exit

@@:
created the error "error A2006: undefined symbol : @@"
some kind of interaction with the macro I guess.

On the surface, your code looks ok.  Give us a fully functioning (or in this case dis-functioning but assembleable) file to play with.
Title: Re: What's wrong with this code
Post by: sebart7 on April 10, 2007, 04:04:14 AM

    xor esi, esi
    mov esi, pfbuff       ; move the address into esi
    jmp count_

Here is no need for xor ESI,ESI .
No mater what You "do" with ESI it will be "overwrited" in next line : mov ESI,pfbuff


    add ecx, 1                        ; keep count of characters in ecx
    add esi, 1
    jmp count_

If You have to add just 1 to "something" You can use INC it increments destination by 1 and its "smaller and faster"
for example :
    INC ECX
    INC ESI
Same You can subtract something by 1 with DEC
for example :
    DEC ECX     ; is like SUB ECX,1
    DEC dword ptr[ESI]    ; ect


And one more thing.
You should always remember that many things (input data) are dynamic and most of time You cant be sure
if given data will be the way You expect it to be, or it even can be completly invalid.
You have to "expect" and be ready for most of things that can be given to You as a input.
For example : You expect that file is terminated by 0 while *.txt files ARENT terminated by 0
Also depends what program (notepad) You use to create *.txt file You may encounter 10 or 10,13 as EndOfLine.
If it hapen, will You count 13 as a CHR ? You may also, have completly nothing at EndOfFile, no 0 no 10 and no 10,13
if *.txt file creator will not press ENTER after last word.
Title: Re: What's wrong with this code
Post by: sinsi on April 10, 2007, 04:16:11 AM
I would use a different way of checking for EOF
    xor esi,esi
    mov edi, pfbuff
    jmp count_
   
  pre_count:
    xor ecx, ecx
    add esi, 1
   
  count_:
    cmp esi,flen
    jae exit_
      cmp byte ptr [edi+esi], 10          ; check for end of line
      je reset_count
      add ecx, 1                        ; keep count of characters in ecx
      add esi, 1
      jmp count_
Title: Re: What's wrong with this code
Post by: Rainstorm on April 10, 2007, 11:12:19 AM
QuoteHow about posting a file with some actual working code?  Trying to assemble your code as you posted it was a problem.
This code:
Code:
jne @F

  print "file open error",13,10
  inkey
  exit

@@:
created the error "error A2006: undefined symbol : @@"
some kind of interaction with the macro I guess.

Jimg the code was assembling properly for me. - To make doubly sure i copied the code in my first post
again & assembled it. - I am not getting any error of the kind you mention.

btw now the character count am getting is some number but its wrong.
sometimes the char count changes to 0 again if i edit the file being tested

sinsi,

i tried with your code.. & its still not functioning proper.

today when i was testing it seems that if there is just 1 line the result becomes zero, & at other times it returns the total characters in the file instead of just the highest in a line.

thanks .
[edit] i guess using the flen is a better way but in the main files i tested there weren't any '0' value
         ascii chars inserted

Title: Re: What's wrong with this code
Post by: hutch-- on April 10, 2007, 11:17:22 AM
I am not sure exactly what you were testing but this mod of your original posted code works fine.



; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

  .data

    pfbuff   dd  0
    flen     dd  0
    fname    db  "\masm32\include\windows.inc",0

  .code

start:

  ; -----------------------
  ; load file into a buffer
  ; -----------------------
    invoke read_disk_file,ADDR fname,ADDR pfbuff,ADDR flen
    test eax, eax
    jnz @F
    print "file open error",13,10
    inkey
    exit
  @@:

    print str$(flen)," Returned file length",13,10  ; display the file length.

    push ebx
    push esi

    xor ebx, ebx                                    ; zero ebx

    mov esi, pfbuff
    sub esi, 1
  @@:
    add esi, 1
    cmp BYTE PTR [esi], 10                          ; test for line feed
    jne nxt
    add ebx, 1                                      ; count lines while scanning lewngth
  nxt:
    cmp BYTE PTR [esi], 0                           ; test for zero
    jnz @B

    sub esi, pfbuff
    print str$(esi)," Scanned file length",13,10
    print str$(ebx)," Scanned file line count",13,10

    pop esi
    pop ebx

    inkey
    exit

    end start



Result is,



1127755 Returned file length
1127755 Scanned file length
30780 Scanned file line count
Press any key to continue ...

Title: Re: What's wrong with this code
Post by: Rainstorm on April 10, 2007, 11:32:20 AM
hutch,

the code i wrote is supposed to return the highest no of characters a line contains.
so as it scans the file, the value in the count1 variable is replaced with higher character counts  other lines might have. & in the end the highest one is displayed.

thanks.
Title: Re: What's wrong with this code
Post by: Rainstorm on April 10, 2007, 11:48:15 AM
sebart7,

thanks for all that info. - when i read a file into a buffer isn't a 0 added at the end ?
QuoteAlso depends what program (notepad) You use to create *.txt file You may encounter 10 or 10,13 as EndOfLine.
-  wasn't aware that 13i could be the end of line thought it was 10 like 13,10

so what do i use to detect an 'end of line'
Title: Re: What's wrong with this code
Post by: sinsi on April 10, 2007, 11:56:01 AM

@@:
    xor esi, esi
    mov esi, pfbuff       ; move the address into esi
    jmp count_

On entry, ECX isn't initialised to 0, so the first time around ECX actually has the file length (as returned by read_disk_file).
Maybe "xor esi,esi" is supposed to be "xor ecx,ecx"?
Title: Re: What's wrong with this code
Post by: hutch-- on April 10, 2007, 12:31:41 PM
I think this does what you want.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

  .data

    pfbuff   dd  0
    flen     dd  0
    count1   dd  0
    fname    db  "\masm32\include\windows.inc",0

  .code

start:

  ; -----------------------
  ; load file into a buffer
  ; -----------------------
    invoke read_disk_file,ADDR fname,ADDR pfbuff,ADDR flen
    test eax, eax
    jnz @F
    print "file open error",13,10
    inkey
    exit
  @@:

    print str$(flen)," Returned file length",13,10  ; display the file length.

    push ebx
    push esi
    push edi

    xor ebx, ebx                                    ; zero ebx
    xor edi, edi                                    ; zero edi

    mov esi, pfbuff
    sub esi, 1


  @@:
    add esi, 1
    add edi, 1
    cmp BYTE PTR [esi], 10                          ; test for line feed
    jne nxt
    add ebx, 1                                      ; count lines while scanning length
    cmp edi, count1
    jle ovrit
    mov count1, edi
  ovrit:
    xor edi, edi
  nxt:
    cmp BYTE PTR [esi], 0                           ; test for zero
    jnz @B


    sub esi, pfbuff
    print str$(count1)," characters longest line length",13,10
    print str$(esi)," Scanned file length",13,10
    print str$(ebx)," Scanned file line count",13,10
   

    pop edi
    pop esi
    pop ebx

    inkey
    exit

    end start

Title: Re: What's wrong with this code
Post by: Jimg on April 10, 2007, 02:09:03 PM
Sinsi had the answer, it's initializing ecx that was the problem.

Your original code will work with that change.  That's not to say it couldn't use some work as others have indicated :wink

There will be a zero byte terminator on the file since the read_disk_file macro will zero memory before reading, and adds an extra 32 bytes just to make sure.  But it would be better form to get the size of the file and process that many bytes.

I am still getting the same error with the @@: that I mentioned. If it works for everyone else, there must be something wrong with my setup.  I'm using Masm 6.15 if it makes a difference.

As to the carriage return problem.  I've always considered a line feed as a change to a new line.  You may find a line feed alone at the end of a line or as you say, usually a 13,10.   So that part should be ok except do you really want to count a carriage return as part of the length of a line?  I'm sure you can figure out the code to count it or not.

And to everyone else, is there a system where a 13 indicates an end of line?  Unix perhaps?  I am working on a program right now that needs this info.  In my experience, a carriage return was meant for a printer to return to the beginning of the current line to do overstrikes, etc.  Only the linefeed actually advanced the line.


Edit:
I was making a debug build of your program, and this was causing the problem with the @@:
Making a release version solved the problem, but I have no idea why it would be a problem in a debug build.  Anyone?
Title: Re: What's wrong with this code
Post by: hutch-- on April 10, 2007, 03:19:40 PM
Jim,

The MAC used to do it that way, ascii 13 only and a later Windows rich edit control  works internally with only and ascii 13.

PS : Also check if you are running a custom "print" macro as the standard masm32 "print" macro has no problems with that style of code layout.
Title: Re: What's wrong with this code
Post by: Jimg on April 10, 2007, 03:34:39 PM
Hutch-
  Well, I'm certainly not going to worry about mac files :snooty:

As for the error, did you try it making a debug build?  I used these parameters - /c /coff /Cp /nologo /Fm /Zi /Zd /Fl /Sn

And I get this-
00000014  33 C9   invoke read_disk_file,addr fname,addr pfbuff, addr flen
00000016  83 F8 00   xor ecx,ecx
  cmp eax, 0
 
F:\WinAsm\Progs\AMiscTests\consoletest2\Console.Asm(26) : error A2006: undefined symbol : @@
  jne @f

     2       LOCAL nustr
= "      2         quot SUBSTR <"file open error">,1,1
     2       IFIDN quot,<">           
00000019 0000002E      2         .data
0000002E 66 69 6C 65 20     2           ??0019 db "file open error",0       
   6F 70 65 6E 20
   65 72 72 6F 72
   00
00000021      2         .code
     2         EXITM <ADDR ??0019>     
00000021  68 0000002E R   *     push   OFFSET ??0019
00000026  E8 00000000 E   *     call   StdOut
     1         invoke StdOut,reparg("file open error")
     1       IFNB <13,10>
     2         LOCAL txtname
0000002B 0000003E      2         .data
0000003E 0D 0A 00      2           ??001A db 13,10,0
0000002B      2         .code
     2         EXITM <OFFSET ??001A>
0000002B  68 0000003E R   *     push   dword  ptr OFFSET FLAT:??001A
00000030  E8 00000000 E   *     call   StdOut
     1         invoke StdOut,chr$(13,10)
     1       ENDIF
  print "file open error",13,10
     1       IFDIF <>,<NULL>                 
     1         IFNB <>                       
     1           print                        ;; print user defined text
     1         ELSE                                    ;; else
     1           print "Press any key to continue ..." ;; print default text
     3       LOCAL nustr
= "      3         quot SUBSTR <"Press any key to continue ...">,1,1
     3       IFIDN quot,<">           
00000035 00000041      3         .data
00000041 50 72 65 73 73     3           ??001B db "Press any key to continue ...",0       
   20 61 6E 79 20
   6B 65 79 20 74
   6F 20 63 6F 6E
   74 69 6E 75 65
   20 2E 2E 2E 00
00000035      3         .code
     3         EXITM <ADDR ??001B>     
00000035  68 00000041 R   *     push   OFFSET ??001B
0000003A  E8 00000000 E   *     call   StdOut
     2         invoke StdOut,reparg("Press any key to continue ...")
     2       IFNB <>
     2         invoke StdOut,chr$()
     2       ENDIF
     1         ENDIF
     1       ENDIF
0000003F  E8 00000000 E     1       call wait_key
     1       print chr$(13,10)
     3         LOCAL txtname
00000044 0000005F      3         .data
0000005F 0D 0A 00      3           ??001C db 13,10,0
00000044      3         .code
     3         EXITM <OFFSET ??001C>
     3       LOCAL nustr
= O      3         quot SUBSTR <OFFSET ??001C>,1,1
     3       IFIDN quot,<">           
     3         .data
     3           ??001D db OFFSET ??001C,0       
     3         .code
     3         EXITM <ADDR ??001D>     
     3       ELSE
     3         EXITM <OFFSET ??001C>             
00000044  68 0000005F R   *     push   dword  ptr OFFSET FLAT:??001C
00000049  E8 00000000 E   *     call   StdOut
     2         invoke StdOut,reparg(OFFSET ??001C)
     2       IFNB <>
     2         invoke StdOut,chr$()
     2       ENDIF
  inkey
     1       IFNDEF
0000004E  6A 00    *     push   +000000000h
00000050  E8 00000000 E   *     call   ExitProcess
     1         invoke ExitProcess, 0
     1       ELSE
     1         invoke ExitProcess,
     1       ENDIF
  exit
00000055
00000055  33 F6 @@:
00000057  8B 35 0000000A R     xor esi, esi
0000005D  EB 05     mov esi, pfbuff       ; move the address into esi


Sorry for the mess, but I would like to get to the bottom of this.  Perhaps you would like to move this part to a new thread?
Title: Re: What's wrong with this code
Post by: hutch-- on April 10, 2007, 05:23:36 PM
Jim,

I have not used debug builds since masm 6.0 in the early 90s in DOS. Does it build OK without the debug build, "/c /coff" minimum style ?
Title: Re: What's wrong with this code
Post by: Jimg on April 10, 2007, 05:30:06 PM
Yes, it assembles with no errors.  (But of course it won't link, but that's not what we're working on.)

Here's the minimum program that has the problem -
.nolist
include \masm32\include\masm32rt.inc
.listall
.code
start:
  jmp @f
  print "x"
@@:
  exit
end start
Title: Re: What's wrong with this code
Post by: hutch-- on April 10, 2007, 05:56:47 PM
Not here it doesn't.


Microsoft (R) Macro Assembler Version 6.15.8803
Copyright (C) Microsoft Corp 1981-2000.  All rights reserved.

Assembling: H:\asm3\rstorm\jimg\jimg.asm
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Volume in drive H is WIN2K_H
Volume Serial Number is 20E8-3719

Directory of H:\asm3\rstorm\jimg

04/11/2007  03:58a                 117 jimg.asm
04/11/2007  03:58a                 997 jimg.obj
04/11/2007  03:58a               2,560 jimg.exe
               3 File(s)          3,674 bytes
               0 Dir(s)  19,336,445,952 bytes free
Press any key to continue . . .
Title: Re: What's wrong with this code
Post by: Rainstorm on April 10, 2007, 06:00:46 PM
QuoteOn entry, ECX isn't initialised to 0, so the first time around ECX actually has the file length (as returned by read_disk_file).
sinsi, that was it, : )  now it functions properly except if there is just one line in the file (then it returns 0 & not the proper character count) - but i realised that was because the EOF is on that 1st line itself so to speak, & I was using the zero terminator to check the EOF.
Same thing was happening with the last code hutch posted, i.e it shows a '0' charactercount if there is just one line in the file. - I will use the 'flen' method & that would eliminate that problem too.
jimg ,  am using the usual 6.14 version that comes with the masm package.

thanks all.

Rainstorm
-

Title: Re: What's wrong with this code
Post by: Jimg on April 10, 2007, 06:05:28 PM
Rainstorm-

Glad you got it all working.  I didn't mean to hijack your thread, I'll start a new thread with my problem.

Title: Re: What's wrong with this code
Post by: Rainstorm on April 10, 2007, 06:25:12 PM
no probs  :)
Title: Re: What's wrong with this code
Post by: Rainstorm on April 12, 2007, 10:58:42 PM
in, the below code ecx becomes 0 in the line  pre_count:
      xor ecx, ecx
yet in the end ecx seems to hold the right character count of the whole file & matches the file length
    mov scanned_length, ecx    <--- that line

how come ? that's weird

    .data

    pfbuff      dd  0
    flen        dd  0
    fname       db  "H:\Project\filetest1.txt",0
    count2      dd  0
scanned_length  dd  0,0
   
;----------------------------------------------------------------------

    .code
start:

  invoke read_disk_file,addr fname,addr pfbuff, addr flen 
  cmp eax, 0
  jne @F

  print "file open error",13,10
  inkey
  exit

@@:
    print "returned file length - "
    print ustr$(flen),13,10
    xor ecx, ecx
    mov esi, pfbuff
    jmp count_
   
  pre_count:

      xor ecx, ecx    <---  ecx 0 here
      add esi, 1
   
  count_:
    cmp ecx, flen           ; check for 'end of file'
    je exit_
    cmp byte ptr [esi], 10  ; check for 'end of line'
    je reset_count
    add ecx, 1           ; keep count of characters in ecx
    add esi, 1
    jmp count_

; --------------------------------------------------------
; replace the value in count1 with ecx if is less than the value in ecx
; --------------------------------------------------------
   
   reset_count:
      cmp ecx, count1
      jna pre_count
      mov count1, ecx
      jmp pre_count

;--------------------
; display the results
;--------------------

exit_:

    mov scanned_length, ecx    <-- ecx still holding the right character count of the whole file here
    free pfbuff

    print "scanned length - "
    print ustr$(scanned_length),13,10

    print "highest character count: - "
    print ustr$(count1),13,10

    inkey
    exit

end start
Title: Re: What's wrong with this code
Post by: Jimg on April 13, 2007, 01:06:40 AM
apparently the very last line is the longest, and it doesn't have a newline on the end.
Title: Re: What's wrong with this code
Post by: Rainstorm on April 13, 2007, 01:22:39 AM
yes that's true too.
i got it
actually because ecx gets reset the loop is running along in the buffer far past the file length.
thx