Hello all,
I am trying understand how to display my values in memory to the user, I want to increment each value aCount, bCount, etc... and display it back to the user when the loop ends. I have tried several ways with no luck and my book sucks, please help:
.386
.MODEL FLAT
INCLUDE io.h
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; linefeed character
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
prompt1 BYTE cr,Lf,Lf,"enter a grade: ", 0
number BYTE 6 DUP (?)
aPrompt BYTE cr, Lf, "A count is: ", 0
bPrompt BYTE cr, Lf, "B count is: ", 0
cPrompt BYTE cr, Lf, "C count is: ", 0
dPrompt BYTE cr, Lf, "D count is: ", 0
fPrompt BYTE cr, Lf, "F count is: ", 0
outOfRange BYTE cr, Lf, " The number entered is out of large "
aCount BYTE 6 DUP (?)
bCount BYTE 6 DUP (?)
cCount BYTE 6 DUP (?)
dCount BYTE 6 DUP (?)
fCount BYTE 6 DUP (?)
.CODE ; start of main program code
_start:
mov ah, 0
mov bx, 0
mov cx, 0
mov dx, 0
mov aCount, 0
beginLoop: cmp eax, -1
je endProgram
withinRange: cmp eax, 100
output prompt1 ; enter the grade
input number, 20 ; get number
atod number ; convert to integer
cmp eax, 90 ; if number >= 90
jge storeA ; goto storeA
cmp eax, 80
jge storeB ; if number >= 80
cmp eax, 70
jge storeC ; if number >= 70
cmp eax, 60
jge storeD ; if number >= 60
jmp storeF ; if number >= 50
storeA:
inc aCount ; add one to aCount
jmp beginLoop ; back to begin
storeB: inc bCount; ; add one to bCount
jmp beginLoop ; back to begin
storeC: inc cCount; ; add one to cCount
jmp beginLoop ; back to begin
storeD: inc dCount; ; add one to dCount
jmp beginLoop ; back to begin
storeF: inc fCount; ; add one to dCount
jmp beginLoop ; back to begin
endProgram:
output aPrompt ; display label, count and prompt
output aCount
input number, 20 ; get number
INVOKE ExitProcess, 0 ; exit with return code 0
PUBLIC _start ; make entry point public
END ; end of source code
Here is a modified version that works with Masm32 macros.
include \masm32\include\masm32rt.inc
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; linefeed character
.DATA ; reserve storage for data
prompt1 BYTE cr,Lf,Lf,"enter a grade: ", 0
number BYTE 20 DUP (?)
aPrompt BYTE cr, Lf, "A count is: ", 0
bPrompt BYTE cr, Lf, "B count is: ", 0
cPrompt BYTE cr, Lf, "C count is: ", 0
dPrompt BYTE cr, Lf, "D count is: ", 0
fPrompt BYTE cr, Lf, "F count is: ", 0
outOfRange BYTE cr, Lf, " The number entered is out of large "
aCount BYTE 6 DUP (?)
bCount BYTE 6 DUP (?)
cCount BYTE 6 DUP (?)
dCount BYTE 6 DUP (?)
fCount BYTE 6 DUP (?)
.CODE ; start of main program code
_start:
mov ah, 0
mov bx, 0
mov cx, 0
mov dx, 0
mov aCount, 0
beginLoop: cmp eax, -1
je endProgram
withinRange: cmp eax, 100
output equ <print offset >
output prompt1 ; enter the grade
invoke StdIn, offset number, 20 ; get number
invoke atol, offset number
; push eax
; print str$(eax), 9, "received", 13, 10
; pop eax
; atod number ; convert to integer
cmp eax, 90 ; if number >= 90
jge storeA ; goto storeA
cmp eax, 80
jge storeB ; if number >= 80
cmp eax, 70
jge storeC ; if number >= 70
cmp eax, 60
jge storeD ; if number >= 60
jmp storeF ; if number >= 50
storeA:
inc aCount ; add one to aCount
jmp beginLoop ; back to begin
storeB: inc bCount; ; add one to bCount
jmp beginLoop ; back to begin
storeC: inc cCount; ; add one to cCount
jmp beginLoop ; back to begin
storeD: inc dCount; ; add one to dCount
jmp beginLoop ; back to begin
storeF: inc fCount; ; add one to dCount
jmp beginLoop ; back to begin
endProgram:
output aPrompt ; display label, count and prompt
print str$(aCount)
invoke StdIn, offset number, 20
; input number, 20 ; get number
INVOKE ExitProcess, 0 ; exit with return code 0
;PUBLIC _start ; make entry point public
END _start ; end of source code
computerbum,
If you are using the Detmer components, the counts are supposed to be 16-bit integers, that when converted to a string will fit in 6 bytes (sign + 5 digits). So for aCount, for example, you need a 16-bit variable to hold the count, and a minimum 7-byte buffer to hold the string and null terminator (I would make it 8 bytes).
Ok, I change by variable to 8 BYTES but I still get the output of a smiley face
This is driving me nuts
changed to:
aCount BYTE 8 DUP (?)
first, this is 16-bit code
way down at the bottom of the forum, you will find a 16-bit subforum
the values are binary
in order to make them easy to understand, you need to convert them to decimal or hexidecimal ASCII strings prior to display
if you search the 16-bit subforum, you are sure to find many routines to do this
although - i recall Detmer has such a routine already written - i forget what it's called
my best advice is to scrap 16-bit code altogether, install the masm32 package, and learn 32-bit
Detmer, Kip, Randy - all good authors, but the libraries they provide are going to be used only in for their book
at some point you will want to move past that
Dave, the Detmer stuff I have is 32-bit code, that I think was adapted from 16-bit code.
computerbum, here is a quick example of what I meant:
.data
count WORD 0
instring BYTE 8 dup(0)
outstring BYTE 8 dup(0)
.code
input instring, 8 ; get string from keyboard
atod instring ; convert to 16-bit integer in AX
mov count, ax
shl count, 1 ; multiply times 2
itoa outstring, count ; convert result to string
output outstring ; and display it
Well, I see how you are doing it with input and I can do that just fine, I just cannot get it to work using memory values
I do see your points made guys and I agree but I am still not getting it to work
Like you said Dave the value is in binary and I need to convert it to ASCII or integer but I do not see any specific macro in my book to do this.
I have looked at all the different ones
dtoa : (destination, source) double to ASCII
atod: (source) ASCII to double
itoa: (destination, source) integer to ASCII
atoi: (source) ASCII to integer
None of these macros will simply take aCount and convert it to ASCII or integer correctly
These are the only one
dtoa and itoa will do the job
although - you may have to make sure the upper word of a register is zero or sign-extended
movzx eax,WordVal
movsz eax,WordVal
so you are saying to just set eax register to zero like so:
mov eax, 0
then:
itoa aCount, eax
Quote from: computerbum on March 18, 2011, 11:07:05 PMNone of these macros will simply take aCount and convert it to ASCII or integer correctly
so you need to write your own functions. here an example for displaying an byte array (decimal):
Quoteinclude masm32rt.inc
.data
aCount BYTE 6 DUP (?)
bCount BYTE 123,213,0,12,1,3,4,112
.code
byte_array_to_sz proc uses esi edi ebx pba:ptr BYTE,nBytes:DWORD
.if nBytes
mov esi,pba
mov eax,nBytes
mov edi,alloc(ADDR [eax*4])
mov ebx,edi
.while nBytes
movzx eax,BYTE ptr [esi]
mov edx,10
div dl
add ah,30h
mov BYTE ptr [edi+2],ah
movzx eax,al
div dl
add ax,3030h
mov BYTE ptr [edi+1],ah
mov BYTE ptr [edi+0],al
mov BYTE ptr [edi+3],20h
lea edi,[edi+4]
lea esi,[esi+1]
dec nBytes
.endw
mov BYTE ptr [edi-4-1],0
mov eax,ebx
.else
xor eax,eax
.endif
ret
byte_array_to_sz endp
main proc
invoke byte_array_to_sz,ADDR aCount,6
.if eax
print eax,13,10
.endif
invoke byte_array_to_sz,ADDR bCount,8
.if eax
print eax,13,10
.endif
inkey
invoke ExitProcess,0
main endp
end main
Sorry man I am a noob, I do not understand that much yet. I am still in the basics
Quote from: computerbum on March 18, 2011, 11:07:05 PM
I have looked at all the different ones
dtoa : (destination, source) double to ASCII
atod: (source) ASCII to double
itoa: (destination, source) integer to ASCII
atoi: (source) ASCII to integer
None of these macros will simply take aCount and convert it to ASCII or integer correctly
My previous statement about 16-bit integers was not correct. While atoi does return a 16-bit integer in AX, atod returns a 32-bit integer in EAX.
In your code you have:
number BYTE 6 DUP (?)
aCount BYTE 6 DUP (?)
bCount BYTE 6 DUP (?)
cCount BYTE 6 DUP (?)
dCount BYTE 6 DUP (?)
fCount BYTE 6 DUP (?)
If these definitions included a trailing null byte they would work acceptably as buffers to hold a decimal input string to be converted to a 16-bit integer or a 16-bit integer converted to a decimal string. But in your code you are using them as integer variables, and because they are defined as bytes MASM sees them as 8-bit integers, so the following instructions:
mov aCount, 0
inc aCount
inc bCount
...
Act on only the first byte of the variables. I now think that aCount, bCount, etc should be defined as 32-bit integers, like so:
aCount DWORD ?
bCount DWORD ?
...
And you should define separate buffers for the strings, sized large enough to hold a 32-bit integer converted to a decimal string, and a null terminator, and in this case padded to a length that is a multiple of 4:
inbuf BYTE 12 dup(0)
outbuf BYTE 12 dup(0)
In your code you also have:
input number, 20 ; get number
For the input macro you are specifying a length that is greater than the actual buffer. The point of having a buffer length parameter is so the code can avoid overflowing the buffer. You should specify the actual buffer length.
movzx eax,WordVal
movsz eax,WordVal
MOVZX zero-extends a word or byte value to 32 bits (use for unsigned values)
MOVSX sign-extends a word or byte value to 32 bits (use for signed values)
if you are using Detmer's 32-bit library, there is a macro named "wtoa" that does what you want
no need to extend the value to 32 bits, as that one ignores the upper 16 bits