News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

What's wrong with this code

Started by Rainstorm, April 09, 2007, 11:50:49 PM

Previous topic - Next topic

Rainstorm

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

Jimg

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.

Rainstorm

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.

dsouza123

[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

Jimg

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.

sebart7


    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.

sinsi

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_
Light travels faster than sound, that's why some people seem bright until you hear them.

Rainstorm

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


hutch--

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 ...

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Rainstorm

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.

Rainstorm

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'

sinsi


@@:
    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"?
Light travels faster than sound, that's why some people seem bright until you hear them.

hutch--

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

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Jimg

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?

hutch--

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.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php