News:

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

parsing a text file

Started by garr, May 20, 2010, 07:55:30 PM

Previous topic - Next topic

garr

I am having a tough time with this one. The teacher wants us to manipulate his code for this project. We have to use a gui interface to boot. This guy doesn't really teach us much, just gives us his code and has us manipulate it. So for this project I have to read in a text file that has ^ (carrots) separating 2 numbers. I then have to save everything to a new file with =answer  appended to each line. My additions start in the middle at the .WHILE statement. I have the original code if anyone wants it. It originally parsed a text file and counted how many @ symbols it found and replaced it with the string "&at". Here is a copy of my text file I made to help with this project
5^6
2^3
1^4
2^2
7^7
-8^2
-5^-5
4^4
The errors I get when compiling are at lines:
126: cannot add two relocatable labels (don't know what this means)
134: invalid use of registers  (which is weird cause the line is mov counter,0)
139: immediate operand not allowed (mov OFFSET temp, BYTE PTR [esi])

thanks in advanced. I am terribly  :dazzled:

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

      DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD

    .data
      base      SDWORD ?
      exponent  SDWORD ?
      product   SDWORD ?
      temp      BYTE   ?            ;10 bytes to hold each number
      counter   SDWORD 0
      outputFileSize SDWORD ?
      hWnd      dd ?
      hInstance dd ?
      pMem      dd ?
      flen      dd ? ; length of input file
      fposition dd ?
      outputString db "? is the char",0
      outputLen dd ? ; length of output file
      outMem    dd ? ; memory for output file
      fileRead  dd 0 ; 1 if there is a file already there
      translated dd 0; counts how many chars are translated
    GETCHAR EQU 200
    SHOWLENGTH EQU 100
    SHOWCHAR EQU 300

    .code
; ########################################################################
;------------------------------------------------------------------------
;This is our recursive procedure that constantly calls itself to multiply
;------------------------------------------------------------------------
power   PROC uses edx,  n1:SDWORD, n2:SDWORD
       
        mov     eax,1           ; n1**0 = 1
        mov     edx, n2         ; move exponent to edx, edx = n2
        cmp     edx, 0          ; compare the exponent to 0, if its zero we are done
        jle     stop            ; goto the return statement
        mov     eax, n1         ; eax = n1
        imul    eax, eax        ; eax = eax (n1) * eax (n1), edx preserved
        shr     edx,1           ; edx = n2 >> 1, carry = n2 % 2
        jnc     L1              ; if it is zero (no carry) then its even so jump to L1
        Invoke  power,eax,edx   ; power(n1*n1, n2 >> 1)
        imul    eax, n1         ; * n1
        jmp     stop            ; return(n1 * power(n1*n1, n2 >> 1))
L1:
        Invoke  power,eax,edx   ; return(power(n1*n1, n2 >> 1)
stop:
        ret                     ; returns answer in eax
power   ENDP
; ########################################################################
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

start:
      mov hInstance, FUNC(GetModuleHandle,NULL)
      call main
      invoke ExitProcess,eax

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    Dialog "Project 4", \         ; caption
           "MS Sans Serif",10, \            ; font,pointsize
            WS_OVERLAPPED or \              ; styles for
            WS_SYSMENU or DS_CENTER, \      ; dialog window
            5, \                            ; number of controls
            50,80,155,100, \                ; x y co-ordinates
            1024                            ; memory buffer size

    DlgButton "Load",WS_TABSTOP,6,20,40,13,IDOK
    DlgButton "Char",WS_TABSTOP,50,20,40,13,GETCHAR
    DlgButton "Cancel",WS_TABSTOP,106,40,40,13,IDCANCEL
    DlgStatic "Length of file",SS_LEFT,5,5,150,9,SHOWLENGTH
    DlgStatic "Char in file",SS_LEFT,5,60,90,9,SHOWCHAR

    CallModalDialog hInstance,0,DlgProc,NULL

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

DlgProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

    LOCAL patn  :DWORD
    LOCAL fname :DWORD
    LOCAL wmsg  :DWORD
    LOCAL str1  :DWORD
    LOCAL buffer[128]:BYTE
    LOCAL ats   :DWORD

    Switch uMsg
      Case WM_INITDIALOG
        invoke SendMessage,hWin,WM_SETICON,1,
                           FUNC(LoadIcon,NULL,IDI_ASTERISK)
        m2m hWnd, hWin
        return 1
      Case WM_COMMAND
        Switch wParam
          Case IDOK
            mov patn, CTXT("Text files",0,"*.asm;*.rc;*.txt;*.bat",0,"Web files",0,"*.htm;*.html;*.xml;*.xhtml",0,"all files",0,"*.*",0)
            mov fname, OpenFileDlg(hWin,hInstance,"Select File to Count @'s",patn)
            cmp BYTE PTR [eax], 0
            jne @F
            return 0
          @@:
            cmp fileRead,1 ; check if there is a file already in
            jne newFile
            free pMem
   newFile:
            mov pMem, InputFile(fname)
            mov flen, len(pMem)
            invoke SetDlgItemText,hWin,SHOWLENGTH,cat$(str$(flen),": length of ",fname)
            mov fposition,0 ; start out at position 0
           
            xor edx,edx ; edx = 0 edx counts the @'s
            mov esi,pMem    ; esi should locate each byte in loaded file
           
            mov ebx,pMem
            add ebx,flen    ; ebx will be the terminator (location of EOF sort of)
            mov outputFileSize,ebx  ;store our new file size
      .WHILE esi <= ebx
            mov counter,0  ;keeps track of how long our string is
            mov [temp + counter], BYTE PTR [esi]   ;copies character by character to temp
            .IF BYTE PTR [esi] == '^'         ;we hit our delimiter
                inc esi
                inc edx
                push esi
                add outputFileSize, LENGTHOF temp
                mov base, sval(temp)
                pop esi
                mov temp, BYTE PTR esi     ;reset temp
                mov counter, 0               ;reset counter
            .ELSEIF BYTE PTR [esi] == 13     ;if we hit the end of the line
               
                inc esi                      ;increment twice to hit new line
                inc esi
                mov OFFSET temp, BYTE PTR [esi]
                mov counter, 0
            .ENDIF
            inc esi
            inc counter
      .ENDW



            mov ats,edx ; keeps cout of at signs
            invoke SetDlgItemText,hWin,SHOWCHAR,cat$(str$(edx)," is the number of Equations")
            mov eax,ats
            imul eax,3
            add eax,flen  ; eax = 3*ats+flen (output file length)
            mov outputLen,eax
            inc eax         ; make buffer a bit bigger
            mov outMem,alloc(eax) ; buffer for output
            mov esi,pMem
            mov edi,outMem
            mov ebx,pMem
            add ebx,flen    ; ebx will be the terminator (location of EOF sort of)
    outLoop:
            cmp BYTE PTR [esi],'^'
            je handleCarrot ; check if esi is an @ and handle it specially
            mov al,BYTE PTR [esi] ; copy char from input to output
            mov BYTE PTR [edi],al
            jmp finishLoop
    handleCarrot:
            inc esi   

    finishLoop:
            inc esi
            inc edi
            cmp esi,ebx
            jl outLoop
            mov fname, SaveFileDlg(hWin,hInstance,"Save File",patn)
            cmp BYTE PTR [eax], 0
            jne @F
            return 0
          @@:
            cmp OutputFile(fname,outMem,outputLen), 0
            invoke SetDlgItemText,hWin,SHOWCHAR,cat$(str$(translated)," characters translated.")
            sub edi,outMem
            invoke SetDlgItemText,hWin,SHOWLENGTH,cat$(str$(edi)," characters to output.")
            jne @F
            MsgBox hWin,"Save operation failed","Problem",MB_OK or MB_ICONEXCLAMATION
            free outMem
            return 0
           
   
            return 0
          @@:
            mov str1, ptr$(buffer)
            mov wmsg, cat$(str1,ustr$(edi)," bytes written to disk")
            MsgBox hWnd,wmsg,"File IO Result",MB_OK
            free outMem
          Case GETCHAR
            mov esi,pMem
            add esi,fposition
            mov al,BYTE PTR [esi]
            mov BYTE PTR [outputString],al
            invoke SetDlgItemText,hWin,SHOWCHAR,ADDR outputString
            mov eax,fposition
            inc eax
            cmp eax,flen
            jl done
            mov eax,0
done:
            mov fposition,eax
            return 0

          Case IDCANCEL
            jmp quit_dialog
        EndSw

      Case WM_CLOSE
        quit_dialog:
         invoke EndDialog,hWin,0
    EndSw

    return 0

DlgProc endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start

clive

Boy, that's some fugly code. I'd probably tear out the core and start over.

Can't do this

          mov [temp + counter], BYTE PTR [esi]   ;copies character by character to temp

You need to get at least one of them in a register, and then copy the character through a register. Can't do mov [mem],[mem] on x86, try a 68K. There is MOVSB/W/D which is [edi],[esi]

  mov edi, counter ; pick appropriate registers for your solution
  mov al,byte ptr [esi]
  mov byte ptr temp[edi],al

plus

temp db 10 dup <?> ;10 bytes to hold each number


              mov temp, BYTE PTR esi     ;reset temp
              mov OFFSET temp, BYTE PTR [esi]

Should be something like

            mov al, byte ptr [esi]
            mov byte ptr temp[0], al

It could be a random act of randomness. Those happen a lot as well.

hutch--

garr,

have played with the basic code, its an "in memory template" dialog and that part of it works OK but the algo is a disaster. It seriously needs a rewrite. Would you post the original code that actually does something.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

Here is one method of parsing the text items you must later calculate.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

      .486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive

;     include files
;     ~~~~~~~~~~~~~
      include \masm32\include\windows.inc
      include \masm32\include\masm32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\Comctl32.inc
      include \masm32\include\comdlg32.inc
      include \masm32\include\shell32.inc
      include \masm32\include\oleaut32.inc
      include \masm32\include\msvcrt.inc
      include \masm32\include\dialogs.inc
      include \masm32\macros\macros.asm

;     libraries
;     ~~~~~~~~~
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\Comctl32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\oleaut32.lib
      includelib \masm32\lib\msvcrt.lib


      calexp PROTO :DWORD,:DWORD,:DWORD,:DWORD

    .data?
        hInstance dd ?

    .data
      args db "7^2",13,10       ; array of arguments
           db "9^3",13,10
           db "7^4",13,10
           db "3^3",13,10
           db "9^2",13,10
           db "8^3",13,10
           db "2^5",13,10
           db "9^2",13,10,0     ; zero terminated array

      pargs dd args             ; pointer to array

    .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

start:

      mov hInstance, FUNC(GetModuleHandle,NULL)

      call main

      invoke ExitProcess,eax

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    Dialog "Calculate Exponent", \          ; caption
           "MS Sans Serif",10, \            ; font,pointsize
            WS_OVERLAPPED or \              ; styles for
            WS_SYSMENU or DS_CENTER, \      ; dialog window
            3, \                            ; number of controls
            50,50,150,120, \                ; x y co-ordinates
            1024                            ; memory buffer size

    DlgButton "Display",WS_TABSTOP,10,20,50,12,IDOK
    DlgButton "Close",WS_TABSTOP,10,35,50,12,IDCANCEL

    DlgStatic "Bare Bones Dialog Written In MASM32", \
              SS_CENTER,2,75,140,9,100

    CallModalDialog hInstance,0,calexp,NULL

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

calexp proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

    LOCAL hArray    :DWORD      ; array handle
    LOCAL acnt      :DWORD      ; array item count
    LOCAL cntr      :DWORD      ; loop counter

    switch uMsg
      case WM_INITDIALOG
        invoke SendMessage,hWin,WM_SETICON,1,rv(LoadIcon,NULL,IDI_ASTERISK)

      case WM_COMMAND
        switch wParam
          case IDOK

          ; ------------------
          ; preserve ESI & EDI
          ; ------------------
            push esi
            push edi

          ; -------------------------------------------------------------
          ; tokenise the text into an array of pointers to each text item
          ; -------------------------------------------------------------

            mov acnt, rv(ltok,pargs,ADDR hArray)
            mov edi, acnt           ; put the array count in EDI
            mov cntr, 0             ; zero the loop counter
            mov esi, hArray         ; load the array address into ESI

          ; hArray is an array of pointers to the members in the .DATA section
          ; acnt is the number of array members
          ; [esi] is the address of the text in each member
          ; by adding 4 to ESI each iteration you step to the next array member

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

          lbl0:
            fn MessageBox,hWin,[esi],str$(cntr),MB_OK
            add esi, 4
            add cntr, 1
            cmp cntr, edi           ; loop through the pointers
            jl lbl0                 ; until the count matches EDI (acnt)

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

            free hArray             ; release the memory allocated in "ltok"

          ; -----------------
          ; restore ESI & EDI
          ; -----------------
            pop edi
            pop esi

          case IDCANCEL
            jmp quit_dialog

        endsw

      case WM_CLOSE
        quit_dialog:
        invoke EndDialog,hWin,0

    endsw

    xor eax, eax
    ret

calexp endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

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