I'm writing a program in .asm which prompts the user to enter a sentence. I have no problems with this but one requirement of the program is to change the format of the sentence by replacing all the spaces (" ") with underscore characters ("_"). How do I go about singling out the spaces and the changing them?

You would have to load the first byte from your string and check to see if it is a space. If it is, then replace that byte with '_'. Otherwise, just check the next byte. You'd repeat this in a loop until you find the end-of-string character.

Which assembly syntax are you using? If you don't know, then are you compiling on DOS, Linux or what?

Edited 3 Years Ago by Assembly Guy

I'm compiling on DOS with TASM? Would I be correct with something along the lines like this or am I getting too complicated? The array prompts the user to enter up a maximum of 60 characters, actlen holds the actual size of the array.

       lea bx, array
       mov cx, actlen
       mov ax, ' '
again: cmp ax, [bx]
       inc bx
       dec cx
       jne again
       je multiple

multiple: mov [bx], '_'
          loop again

That's nice code, but I think it'll replace the character after the space with an underscore; you increment BX before you store the underscore. Also, you're comparing words (cmp AX, [bx]), not bytes, so your code will never find any spaces.

To simplify your code, you might want to make use of the lodsb and loop instructions. See http://faydoc.tripod.com/cpu/lodsb.htm and http://faydoc.tripod.com/cpu/loop.htm for details. Basically, lodsb will load a byte from the segment:offset pair DS:SI into al and increment SI all in one. loop will decrement CX and jump to the specified label if CX != 0. You could also try storing a null character just after the string to denote the end of the string. While it uses up one extra byte in memory, it makes code much tidier and smaller, for example:

array db "imaginary input",0
    mov si, array

.checkloop:
    lodsb           ; Load next byte into AL and increment SI
    cmp al, 0       ; End of string?
    jz .quit        ; If so, quit the loop
    cmp al, ' '     ; Is the character a space?
    jnz .checkloop  ; If not, load the next byte
    dec si          ; Move back to the address of the space
    mov al, '_'     ; Put character to store in AL
    stosb           ; Store the underscore over the space
    jmp .checkloop  ; Loop
.quit:
    ; do something else...

You could use loop with lodsb like this:

    mov si, array
    mov cx, actlen
.checkloop:
    lodsb           ; Load next byte into AL and increment SI
    cmp al, ' '     ; Is the character a space?
    jz .replace     ; Replace it if it is
    loop .checkloop ; Loop until end of string
    jmp .quit       ; Jump over our .replace function
.replace:
    dec si          ; Move back to the address of the space
    mov al, '_'     ; Put character to store in AL
    stosb           ; Store the underscore over the space
    jmp .checkloop
.quit:
    ; do something else...

Whatever you prefer, I just find that using null-terminated tends to make code more linear, ie. not jumping all over the place. It's up to you.

Edited 3 Years Ago by Assembly Guy

Yeah I see your point, the code becomes much easier to follow and to understand with your way rather than have multiple jumps going up and down the lines of code; especially if I was to come back and make changes or improvements. Thanks for your help on the matter.

This question has already been answered. Start a new discussion instead.