Search code examples
assemblydosx86-16emu8086

why does the interruption int 21h ignore all strings after writing a string filled durring the execution of the program?


i am trying to print the sum of two 16Bit values so am calculating the sum then constructing the string that contains it but the problem is after i print said string any writing interruptions mov ah,09 int 21h are completely ignored, i am using emu8086, here is the code

org 100h

    mov ax,2000
    mov bx,3200
    add ax,bx
    mov si,offset result+5
    mov [si],'$'
    mov bx,10

    Fill:

        dec si
        mov dx,0
        div bx
        add dl,48
        mov [si],dl
        test ax,ax

    jnz Fill

    mov dx,offset result
    mov ah,09h
    int 21h

    mov ah,09h
    mov dx,offset msg
    int 21h

ret

result db 5 dup (?)
msg db " is the sum$"
\n db 0ah,0dh, '$'

it just prints result and ignors msg


Solution

  • result db 5 dup (?)
    msg    db " is the sum$"
    

    With these data definitions, memory is set up as follows:

    result 0    <- offset result+0
           0    <- offset result+1
           0    <- offset result+2
           0    <- offset result+3
           0    <- offset result+4
    msg         <- offset result+5   <- offset msg+0
           i                         <- offset msg+1
           s                         <- offset msg+2
                                     <- offset msg+3
           t                         <- offset msg+4
           h                         <- offset msg+5
           e                         <- offset msg+6
                                     <- offset msg+7
           s                         <- offset msg+8
           u                         <- offset msg+9
           m                         <- offset msg+10
           $                         <- offset msg+11
    

    When you write the terminating $ for your result at offset result+5, you overwrite that space character by which the msg text starts. This in turn means that when you ask DOS to display the msg text, DOS immediately stumbles upon the string terminator and so nothing gets displayed.

    The solution is NOT to write the $ character at offset result+4

    Instead you need to enlarge the buffer for the result so it can hold 6 bytes.
    The value in the AX register that you convert could require 5 digits. Therefore you need a buffer of 5+1 bytes.

    result db 6 dup (?)
    

    As a shortcut that avoids having to write the $ character via the code have:

    result db 5 dup (?), '$'
    

    mov dx,offset result
    mov ah,09h
    int 21h
    

    Using the offset of result could produce garbage on screen!
    The good solution here is to use the value in the SI register at the end of the conversion. It already points at the first digit of the number. How convenient!

        org  100h
    
        mov  ax, 2000
        mov  bx, 3200
        add  ax, bx
        mov  si, offset result+5
        mov  [si], '$'
        mov  bx, 10
    
    Fill:
    
        dec  si
        xor  dx, dx
        div  bx
        add  dl, '0'
        mov  [si], dl
        test ax, ax
        jnz  Fill
    
        mov  dx, si            <- This is offset of first digit.
        mov  ah, 09h
        int  21h
    
        mov  ah, 09h
        mov  dx, offset msg
        int  21h
        ret
    
    result   db 6 dup (?)
    msg      db " is the sum$"