Search code examples
assemblydosx86-16

Copying symbols from the 0ah input to another variable


The task sounds like: "Enter the s1 string at least 10 characters in length. Copy the last but one character three times and the first from string s1 to string s2. Display the lines s1 and s2."

I've tormented with this code for two days and still can't achieve the result, as well can't understand how to fix it. We've learnt for now only 0Ah, 02h, 09h and 40h functions besides int21h / 4ch. For the code below compilation doesn't allow me to enter anything and prints 3 symbols which are pretty similar to the 6.

.model small
.stack
.data

m1 db "Enter the string:", 10, 13,  "$"
maxlength db 11
clength db ?
s1 db 11 dup(?)
s2 db 5 dup(?)
nline db 10,13,"$"

.code

mov ax, @data
mov ds, ax

mov ah, 9
lea dx, m1
int 21h

mov ah, 0Ah
lea dx, s1
int 21h

mov bl, clength
mov bh, 0

mov AL, s1[BX-2]
mov s2+1, AL

mov AL, s1[BX-2]
mov s2+2, AL

mov AL, s1[BX-2]
mov s2+3, AL

mov AL, s1[BX+1]
mov s2+4, AL

mov s2+5, "$"
mov s1[bx], "$"

mov ah, 9
lea dx, s1
int 21h

mov ah, 9
lea dx, nline
int 21h

mov ah, 9
lea dx, s2
int 21h

mov ah, 9
lea dx, nline
int 21h

mov ah, 4ch
int 21h
end

I expect the output to be: Enter the string (the string I print)

(symbols copied from s1)


Solution

  • mov ah, 0Ah
    lea dx, s1
    int 21h
    

    In your program the address for this DOS function needs to become "maxlength".
    You could also write this as lea dx, [s1-2].

    The actual buffer that DOS requires is:

    MyInput db 11, 0, 11 dup(?)
    
    mov ah, 0Ah
    lea dx, MyInput
    int 21h
    

    You can read more about the 0Ah DOS function in How buffered input works.


    and the first from string s1

    You've solved this by writing:

    mov AL, s1[BX+1]
    mov s2+4, AL
    

    This is not correct. At s1[bx+1] there's only garbage in memory. You can fetch the 1st character of s1 via mov al, s1.


    mov AL, s1[BX-2]
    mov s2+1, AL
    mov AL, s1[BX-2]
    mov s2+2, AL
    mov AL, s1[BX-2]
    mov s2+3, AL
    mov AL, s1[BX+1]
    mov s2+4, AL
    mov s2+5, "$"
    

    The s2 string has but 5 positions available. Your adding of +1 to +5 will write behind this buffer! This will destroy your NewLine string.
    You need to use additions from +0 to +4 to stay within the bounds of the buffer.

    mov AL, s1[BX-2]
    mov s2, AL            NEW
    mov AL, s1[BX-2]
    mov s2+1, AL          NEW
    mov AL, s1[BX-2]
    mov s2+2, AL          NEW
    mov AL, s1            NEW
    mov s2+3, AL          NEW
    mov s2+4, "$"         NEW
    

    And of course you don't need to read that second to last character 3 times.

    mov al, s1[bx-2]
    mov s2, al
    mov s2+1, al
    mov s2+2, al
    mov al, s1
    mov ah, "$"
    mov s2+3, ax