1

I have a homework question to get from user up to 8 char in the string in a new line and print it on reverse

I wrote a code that should take every bit from string and put it in the stack and then take it back to the string so it's will be in reversing and print it in the new line. But when I run the file it's just stuck on input and does't give me to do something

I'm new to assembly, we use tasm1~1.4.

there is my code:

    STA SEGMENT STACK
        DB 100H DUP (0)
    STA ENDS

    DATA SEGMENT
        MSG1 DB 'ENTER STRING (Maximum is 8) : $'
        MSG2 DB 'REVERS IS : $'
        ISTR DB 10 DUP(0)
    DATA ENDS

    CODE SEGMENT
        ASSUME CS:CODE,DS:DATA,SS:STA
    MAIN:
        MOV AX, DATA
        MOV DS, AX
        LEA DX, MSG1
        MOV AH, 09H
        INT 21H
        MOV DX, 0
    ;INPUT
        MOV DX, OFFSET ISTR
        MOV AH, 0AH
        INT 21H
        MOV SI, DX
        MOV CL, [SI+1]
        ADD SI, 2
        MOV DX, 0
        MOV BL, CL
    TOSTACK:
        MOV DX, [SI]
        PUSH DX
        INC SI
        LOOP TOSTACK
        MOV DL, 10
        MOV AH, 02H
        INT 21H
        LEA DX, MSG2
        MOV AH, 09H
        INT 21H
        MOV DX, 0
        MOV CL, BL
        MOV SI, 2
    FROMSTACK:
        POP DX
        MOV AH, 02H
        INT 21H
        INC SI
        LOOP FROMSTACK

        MOV AX, 4C00H
        INT 21H

    CODE ENDS
        END MAIN
  • 1
    Comment your code especially if you want others to help. Learn to use a debugger (e.g. the very user friendly turbo debugger) to single step your code and see where it goes wrong. – Jester Dec 20 '18 at 17:31
  • The slow `loop` instruction uses CX (in 16-bit mode), not just CL. You're writing CL but I don't see you zero-extending into CX. IDK why you're storing into memory at `[si+1]` before pushing, though. If you're going to store manually, just make a buffer and `dec` a pointer into it while reading input, then loop forwards over it while writing. (Or pass the whole buffer to a write-string function.) – Peter Cordes Dec 20 '18 at 17:44

1 Answers1

2

But when I run the file it's just stuck on input ...

This is because when using the DOS input function 0Ah, you need to tell DOS beforehand the size of your input buffer. With a definition like ISTR DB 10 DUP(0) you've actually requested no buffer at all!
A correct definition in your program is

ISTR DB 9, 0, 9 DUP(0)

The 1st byte specifies the size of the input buffer. Put it at DesiredNumberOfCharacters + 1.
The 2nd byte specifies how many characters the buffer already contains. Put it at zero.

You can find much more information about this DOS function in another post of mine How buffered input works.

Once your input works, you need to fix a few problems in the TOSTACK part of your program:

  • The LOOP instruction depends on the whole CX register, but you only filled CL which is the low byte of CX. Simply add mov ch, 0.
    This obviously means that you also need to copy to BX instead of to BL in preparation for the FROMSTACK part.
  • Because the user could have chosen to not supply any character at all, your program needs to be prepared for this case. A mere jcxz EXIT will suffice.
  • Each character from the input buffer is held in a byte. Your code should thus not be reading words.

.

    mov     si, offset ISTR + 1
    mov     cl, [si]     ; Characters read 0, 1, 2, ... 8
    mov     ch, 0
    jcxz    EXIT
    mov     bx, cx       ; Save count
TOSTACK:
    inc     si
    mov     dl, [si]     ; This is a byte
    push    dx           ; Don't care about high byte in DH
    loop    TOSTACK

    ...

    mov     cx, bx       ; Restore count ( is GT 0 )
FROMSTACK:
    pop     dx           ; Still don't care about DH
    mov     ah, 02h
    int     21h
    loop    FROMSTACK
EXIT:
    mov     ax, 4C00h
    int     21h

Getting rid of the slow LOOP instruction is easy:

    mov     si, offset ISTR + 1
    mov     cl, [si]     ; Characters read 0, 1, 2, ... 8
    mov     ch, 0
    jcxz    EXIT
    mov     bx, cx       ; Save count
TOSTACK:
    inc     si
    mov     dl, [si]     ; This is a byte
    push    dx           ; Don't care about high byte in DH
    dec     cx
    jnz     TOSTACK

    ...

FROMSTACK:
    pop     dx           ; Still don't care about DH
    mov     ah, 02h
    int     21h
    dec     bx
    jnz     FROMSTACK
EXIT:
    mov     ax, 4C00h
    int     21h
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • If you get rid of `loop`, you can just use `dec cl` / `jnz`. One of the benefits of not using `loop` is your choice of loop condition. – Peter Cordes Dec 23 '18 at 21:28
  • @PeterCordes I kept the word extension because it gave shorter encodings in `dec cx` and `dec bx`. Two bytes shaved off... – Sep Roland Dec 23 '18 at 21:31
  • If you're optimizing for code-size and/or a real 8086 (where code-fetch is the main perf bottleneck, so saving space inside the loop is a win), then you *should* use `loop`. It's slow on 486 and later, I think, but it's actually good on original 8086. – Peter Cordes Dec 23 '18 at 21:44
  • Thanks, I will test it. I just started to learn The Assembly. – Sergei Gaidachevsky Dec 23 '18 at 22:20