News:

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

Help Request

Started by spaarkz, November 24, 2007, 01:35:29 AM

Previous topic - Next topic

spaarkz

Hi

If I have defined 10 bits, say - word db 10 DUP (?)

And I run my program when there is less than 10 characters for example 8, the remaining two characters from the last time the program was run are displayed.

How do I only display 8 characters with the remaining two blank if I have defined 10?

Thanks


jj2007

Windows recognises the end of a string when it meets a 0 byte. So you must somehow poke a 0 after your 8th byte. If we saw your complete code, or at least the part that loads the dup 10, we could give advice...

raymond

Some of the Windows function do require that a string must contain a "0" to indicate where it terminates. Such strings are called null-terminated strings. In the old DOS days, the required terminating character used to be the "$" character for some of the DOS functions.

However, other Windows functions (and some DOS functions) require that the number of characters to be processed must be explicitely provided as a parameter. As jj2007 indicated, a bit more of your code where you attempt to display your string would definitely help us in helping you.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

spaarkz

#3
Thanks

This code is supposed to input a word or message and code it by decrementing the first letter by 1 and the 2nd letter by two etc

I have not grasped the repeat function yet, so this is a little long winded but it appears to work, but if i type a letter less than 9 letters the program outputs the characters held in the remaining memory space from the last time the program was run.

Ideally the program needs to stop coding once the counter = the number of characters entered by the user. 

.486
.model flat, stdcall
option casemap:none

include c:\masm32\work\headings.inc       
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.data
   
    request     db "Type a word (Maximum of 9 letters) that you would like coding & press enter",13,10,0   ; screen output

.data?

    word1       db      9  dup(?)                                      ; space allocated for word to be entered
    word2       dword   9  dup(?)                                      ; space allocated for
    clock       db      1   dup(?)                                     ; space allocated for
   
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.code

main proc

        mov ecx,0
        mov ebx,0
        mov eax,0
 
        invoke      StdOut,     ADDR request                                     ; display request on screen
        invoke      StdIn,      ADDR word1,LENGTHOF word1              ; allow 9 bit word to be entered
               
        mov         ecx,        offset  word1                           ; move offset address of entered word to edx
        mov         ebx,        offset  word2                           ; move offset address of word 2 to ebx
        mov         clock,    1                                             ; set clock to 1
                   
        mov ecx, offset word1
        mov ebx, offset word2
     
        mov ax, [ecx]
        sub al, clock
        mov [ebx],al
        inc clock

        mov ax, [ecx+1]
        sub al, clock
        mov [ebx+1],al
        inc clock

        mov ax, [ecx+2]
        sub al, clock
        mov [ebx+2],al
        inc clock

        mov ax, [ecx+3]
        sub al, clock
        mov [ebx+3],al
        inc clock

        mov ax, [ecx+4]
        sub al, clock
        mov [ebx+4],al
        inc clock

        mov ax, [ecx+5]
        sub al, clock
        mov [ebx+5],al
        inc clock

        mov ax, [ecx+6]
        sub al, clock
        mov [ebx+6],al
        inc clock

        mov ax, [ecx+7]
        sub al, clock
        mov [ebx+7],al
        inc clock

        mov ax, [ecx+8]
        sub al, clock
        mov [ebx+8],al
        inc clock

        print "This is your coded word",13,10
        invoke StdOut,ADDR word2                                       ;display result on screen         

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
invoke ExitProcess,0
main endp
end main                                                    ; Tell MASM where the program ends
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

MichaelW

StdIn will trim the input to the length specified, if necessary, and then add a null terminator. To avoid having this null terminator overwrite the next byte after the buffer, the length specified in the call to StdIn must be at least one byte less than the length of the buffer. As coded your buffers have a length of 9 bytes and LENGTHOF is returning 9. Since the return value for LENGTHOF acts as a constant, you can do arithmetic on it within the instruction statement (e.g. LENGTHOF word1 - 1)

Your code is copying 9 bytes to the output regardless of the number of characters (bytes) entered. You can determine when you have reached the end of the input by checking for the null terminator.

StdOut expects the string to be null-terminated, so you need to add a null terminator at the end of the encoded string.

Instead of handling each byte of the input in separate blocks of code, it would be more efficient to do it in a loop. As pseudo code:

p1 = 32-bit register that contains the address of the input buffer
p2 = 32-bit register that contains the address of the output buffer
cnt = 32-bit register that initially contains the value 1
startofloop:
  get input byte (e.g. mov al, [p1+cnt-1])
  test the value of the byte and if it is zero exit the loop
  encode the byte by subtracting the low-order byte of cnt from it
  store the byte in the output buffer
  increment cnt
  store a null terminator at the end of the output buffer (e.g. mov BYTE PTR [p2+cnt-1], 0)
repeat the loop

The step that stores the null terminator at the end of the output buffer within the loop makes the code simpler. If the next byte from the input buffer is the null terminator then the null terminator for the output buffer will be in place. Otherwise the null terminator for the output buffer will be overwritten with the next encoded byte and the process will continue.
eschew obfuscation

spaarkz

Thanks

I have managed to loop the program using the repeat function but when I try to while the output register it does not work. The code as displayed does code a word but again does not nullify.

If I try the byte ptr(which from what I understand allows different size data to move to normally restricted data size registers) i get errors.

Matt

.data   
        MsgBoxText  db "Press OK Then Type a word (Maximum of 9 letters) that you would like coding & press Enter",0
        MsgCaption  db "  London SouthBank University Microprocessors  ",0
.data?

    p1       db      31  dup(0)                                         ; space allocated for word to be entered
    p2       dword   32  dup(0)                                         ; space allocated for
    cnt      db      1  dup(0)                                          ; space allocated for
     
     
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.code

main proc
     
        invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK
        invoke      StdIn,      ADDR p1,LENGTHOF p1                  ; allow 32 bit word to be entered
               
        mov         ecx,        offset  p1                           ; move offset address of entered word to edx
        mov         ebx,        offset  p2                           ; move offset of allocated space for coded to ebx
        mov         cnt,1                             
        mov         p2,0         
        mov ecx, offset p1
        mov ebx, offset p2
     
       .repeat                                                       ;while the al register is less than 0 follow code
        mov ax,[ecx+esi]                                             ;mov address of ecx + esi to ax register
        sub al, cnt                                                  ;subtract value of cnt from al register
        mov [ebx+esi],al                                             ;mov value of al to address of ebx +esi (P2 to display)
        inc cnt                                                      ;increment counter   
        inc esi                                                      ;increment esi
       .until al==0
       
print "This is your coded word",13,10

invoke StdOut,ADDR p2                                                ;display result on screen         

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
invoke ExitProcess,0
main endp
end main                                                    ; Tell MASM where the program ends
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

raymond

Quotep1       db      31  dup(0)
Because you should retain one byte for a terminating 0, that would allow only 30 bytes of input (and not 32). One suggestion for retaining the full buffer size for input could be:
p1       db      32  dup(0)
p1_0     db      0

Quotep2       dword   32  dup(0)
Since you are going to use this variable for a string no larger than that in p1, there is no need to declare that variable as dword. It should be declared as bytes like p1.

You are using the ESI register as an incremental counter for the pointer into the string. However, that register cannot be expected to have a value of 0 when your program starts (NONE of the registers are expected to have a reliable value when the program starts). Rezero that ESI register before the .repeat loop and you should have better results.

Quotemov ax,[ecx+esi]
Because you are processing only one byte at a time (the one in the AL register), there is no need to get two bytes from memory into the AX register.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com