News:

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

help needed to display memory value correctly

Started by computerbum, March 18, 2011, 12:13:57 AM

Previous topic - Next topic

computerbum

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


jj2007

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

MichaelW

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).
eschew obfuscation

computerbum

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 (?)

dedndave

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

MichaelW

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

eschew obfuscation

computerbum

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



dedndave

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

computerbum

so you are saying to just set eax register to zero like so:


mov eax, 0

then:

itoa aCount, eax

qWord

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
FPU in a trice: SmplMath
It's that simple!

computerbum

Sorry man I am a noob, I do not understand that much yet. I am still in the basics

MichaelW

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

dedndave

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