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.
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,
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.
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
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.
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
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
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
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
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
incorrecltyReplace:
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