News:

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

Intro and Loop question

Started by drinkjetfuel, April 30, 2011, 10:51:31 PM

Previous topic - Next topic

drinkjetfuel

Hi !

First off this is by far one of the best assembly forums I've encountered.

I've always wanted to learn a programing language not necessarily to become a professional developer but more so for personal knowledge.

I'm having trouble figuring out how to output the amount of times a loop has been run.  In the program below I'm supposed to convert an integer into a letter grade, while displaying a counter of how many grades have been converted to the program below:




INCLUDE Irvine32.inc

.data
str1 BYTE "Enter numeric score: ",0
str2 BYTE "Your Grade is:   ",0
str3 BYTE "ROBOT ERROR",0
str4 BYTE "Scores Converted:  ",0

.code
main PROC

call clrscr

L1: mov edx,OFFSET str1
call WriteString
call ReadInt
call Crlf
.IF (eax > 0) && (eax <= 100)
mov  edx,OFFSET str1
   
.IF eax >= 90
mov al,'A'
.ELSEIF eax >= 80
mov al,'B'
.ELSEIF eax >= 70
mov al,'C'
.ELSEIF eax >= 60
mov al,'D'
.ELSE
mov al,'F'
.ENDIF

mov edx,OFFSET str2
call WriteString
call WriteChar
call crlf
call crlf
mov edx,offset str4
call writestring
call crlf
call crlf
loop L1 

.ELSE
mov edx,OFFSET str3
call Writestring

call crlf
call crlf
.ENDIF


exit
main ENDP
END main 


I've searched the forums and read the recent post regarding "Counting, Adding....." I'm just having trouble applying that information to this program.

Thank you in advance for any help or guidance.  I look forward to eventually being able to contribute here.


baltoro

It's pretty simple, assuming the code you posted compiles and works correctly (I don't have access to the Irvine code library).
You would just add a variable in the .data section to use as a counter, and increment it once in every loop execution. You could use a register, but, I have no idea what registers the Irvine routines that you call in your loop write to (but, you could use a push-pop before and after those routines to save the value).
This counter value would then be displayed with the other data.
Is there an Irvine routine that converts a numeric value to a string? There must be, I just don't know what the name of it is.
Baltoro

MichaelW

baltoro,

The WriteInt procedure writes a signed 32-bit integer to standard out.

drink,

Don't forget to initialize the counter to zero when you define it.



eschew obfuscation

drinkjetfuel

Thank you for the feedback.

MichaelW,

Would I initialize the counter to zero outside of the loop? ( are you referring to the a "mov ecx,0" )

Baltoro,

I've experimented with assigning a variable I just can't seem to get the syntax or "counter" to display without error.


Thanks.

I need to do more reading

drinkjetfuel

Quote from: MichaelW on April 30, 2011, 11:19:51 PM
baltoro,

The WriteInt procedure writes a signed 32-bit integer to standard out.

drink,

Don't forget to initialize the counter to zero when you define it.


I've experimented with the call writeint / call writedec command but it would display an integer that was not the counter value.

hutch--

Hi Drink,

Great nick. If you are learning assembler for yourself and not just doing a course, you will probably get much better results using the MASM32 project as its later and very well understood by a large number of members. I don't like to be a critic of other peoples work but the Irvine code is old design with lousy architecture and it has nothing like the range of the full Windows API and Intel istruction set.

Here is a simple example that displays numbers.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    .data
      lf db 0Dh,0Ah,0   ; zero terminate CRLF
      plf dd lf         ; pointer to it

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey               ; wait for a keypress
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL pbuf  :DWORD
    LOCAL bytes[32]:BYTE

    push ebx
    push esi

    lea eax, bytes  ; get the address of the "bytes" buffer
    mov pbuf, eax   ; copy it to a pointer

    mov esi, 10     ; loop counter
    or ebx, -1      ; set EBX to -1

  lbl0:
    add ebx, 1
    invoke ltoa,ebx,pbuf    ; convert EBX to a string
    invoke StdOut,pbuf      ; display it
    invoke StdOut,plf       ; append a CRLF
    sub esi, 1
    jnz lbl0
   
    pop esi
    pop ebx

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

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

dedndave

for the LOOP instruction, the counter is ECX
which you need to initialize   :P
       mov     ecx,100

loop00:
       loop     loop00

will loop 100 times

WriteInt displays the ascii decimal conversion of the binary value that is in EAX
it preserves all registers across the call
so, if you want to see what is in ECX...
       xchg    eax,ecx
       call    WriteInt
       xchg    eax,ecx

we temporarily swap the values in EAX and ECX
once the "ECX" value has been displayed, we swap them back so the LOOP instruction will work

        mov     ecx,100

loop00: xchg    eax,ecx
        call    WriteInt
        xchg    eax,ecx
        loop     loop00

will display 100 to 1, counting backwards
we didn't add any spaces or carriage return/line feeds, so they will all be run together

drinkjetfuel

Quote from: hutch-- on May 01, 2011, 01:52:22 AM
Hi Drink,

Great nick. If you are learning assembler for yourself and not just doing a course, you will probably get much better results using the MASM32 project as its later and very well understood by a large number of members. I don't like to be a critic of other peoples work but the Irvine code is old design with lousy architecture and it has nothing like the range of the full Windows API and Intel istruction set.


No kidding.  I'm learning assembler through an online course which is based off of irvine32.inc.. Once I'm done with this class I'm switching over to MASM32 project.  Professionally I'm switching from mechanical design to IT eventually specializing in security. 


Quote from: dedndave on May 01, 2011, 01:52:53 AM
for the LOOP instruction, the counter is ECX
which you need to initialize   :P
       mov     ecx,100

loop00:
       loop     loop00

will loop 100 times

WriteInt displays the ascii decimal conversion of the binary value that is in EAX
it preserves all registers across the call
so, if you want to see what is in ECX...
       xchg    eax,ecx
       call    WriteInt
       xchg    eax,ecx

we temporarily swap the values in EAX and ECX
once the "ECX" value has been displayed, we swap them back so the LOOP instruction will work

        mov     ecx,100

loop00: xchg    eax,ecx
        call    WriteInt
        xchg    eax,ecx
        loop     loop00

will display 100 to 1, counting backwards
we didn't add any spaces or carriage return/line feeds, so they will all be run together

Thank you for this.  I have everything aligned perfectly I just have to switch it around so that the display will start at 1 and go up to 100ish


drinkjetfuel

#8
Got it working ! Thank you all for the help, greatly appreciated.


INCLUDE Irvine32.inc

.data
str1 BYTE "Enter numeric score: ",0
str2 BYTE "Your Grade is:   ",0
str3 BYTE "ROBOT ERROR",0
str4 BYTE "Scores Converted:  ",0

.code
main PROC

call clrscr
mov ecx,0

L1:
call crlf
mov edx,OFFSET str1 ;Text
call WriteString
call ReadInt
.IF (eax > 0) && (eax <= 100) ;Determine whether to display error or determine range of integer for conversion
mov edx,OFFSET str1

.IF eax >= 90 ;Determining the range of the Integer for conversion
mov al,'A'
.ELSEIF eax >= 80
mov al,'B'
.ELSEIF eax >= 70
mov al,'C'
.ELSEIF eax >= 60
mov al,'D'
.ELSE
mov al,'F'
.ENDIF

mov edx,OFFSET str2 ;Text
call WriteString
call WriteChar
call crlf
mov edx,offset str4
call writestring

add ecx,1 ;Counter --- Getting this to work was tricky
xchg ecx,eax
call Writedec
inc eax
xchg ecx,eax

call crlf
loop L1 

.ELSE ;Error when anything but 1-100 is entered
call crlf
mov edx,OFFSET str3
call Writestring

call crlf
call crlf
.ENDIF


exit
main ENDP
END main 



RuiLoureiro

JetFuel,
Quote
         add ecx,1          ;Counter --- Getting this to work was tricky
         xchg ecx,eax
         call Writedec
         inc eax
         xchg ecx,eax

    We dont need to use tricks here!
    Simple, you are using the loop instruction incorreclty

Replace:
        loop L1

By:
        jmp  L1

AND

Replace this:

add ecx,1    ;Counter --- Getting this to work was tricky
xchg ecx,eax
call Writedec
inc eax
xchg ecx,eax


By This:

                  add   ecx, 1
                  mov   eax, ecx
                  call  WriteDec


If you want to execute a loop 20 times you should use something like this

        mov     ecx, 20
_Loop1: push    ecx

        ;
        ; Do what you want here
        ;
       
        pop     ecx
        loop    _Loop1

This is the safe way to use loop

Run this code and see what the trick does


INCLUDE Irvine32.inc

PrintDec    proto   :DWORD

.data
str1 BYTE "Enter numeric score: ",0
str2 BYTE "Your Grade is:   ",0
str3 BYTE "ROBOT ERROR",0
str4 BYTE "Scores Converted:  ",0

Info1   db "Trick ", 0
_CRLF   db 13, 10, 0
.code
main PROC

call clrscr
mov ecx,0

L1:
call crlf
mov edx,OFFSET str1 ;Text
call WriteString
call ReadInt
.IF (eax > 0) && (eax <= 100) ;Determine whether to display error or determine range of integer for conversion
mov edx,OFFSET str1

.IF eax >= 90 ;Determining the range of the Integer for conversion
mov al,'A'
.ELSEIF eax >= 80
mov al,'B'
.ELSEIF eax >= 70
mov al,'C'
.ELSEIF eax >= 60
mov al,'D'
.ELSE
mov al,'F'
.ENDIF

mov  edx,OFFSET str2 ;Text
call WriteString

call WriteChar
call crlf
mov edx,offset str4
call writestring

add ecx,1 ;Counter --- Getting this to work was tricky
xchg ecx,eax
call Writedec
inc eax
xchg ecx,eax

                  invoke    PrintDec, ecx

                  ;add   ecx, 1
                  ;mov   eax, ecx
                  ;call  WriteDec

call crlf
loop L1 
      ;jmp       L1
.ELSE ;Error when anything but 1-100 is entered
call crlf
mov edx,OFFSET str3
call Writestring

call crlf
call crlf
.ENDIF

call WaitMsg                   ;<<<<<<<<<<<<<<<< Stop here
exit
main ENDP
;-----------------------------
PrintDec    proc    Val:DWORD
            pushad

      mov  edx, offset _CRLF
      call WriteString

      mov  edx, offset Info1
      call WriteString

            mov   eax, Val
            call  WriteDec

      mov  edx, offset _CRLF
      call WriteString

            popad
            ret
PrintDec    endp
END main