This is the main program:

extern        concat:far

stackseg    segment    stack
        bBuffer        byte      100 DUP(?)
stackseg    ends

dataseg        segment
        szMsg1        BYTE      ' Hello World!'
        szMsg        BYTE    '2 1', 13,10,'$'
        iData        BYTE      '123456789012'
        szMsg2      BYTE    ' The Art of Assembly Language Programming',13,10,'$'
dataseg        ends

codeseg        segment
    assume        cs:codeseg, ds:dataseg, es:dataseg, ss:stackseg
    START:
        mov        ax, dataseg
        mov        ds, ax
        mov        es, ax
        lea        si, szMsg1                ;Set the first string's address and length
        mov        BYTE ptr , 12       
        lea        bx, szMsg2                ;Set the second string's address and length
        mov        BYTE ptr , 43       
        lea        di, szMsg                ;Set the concatenated string's address
        call        concat                    ; Call subprogram

        lea        dx, szMsg               
        inc        dx                       
        mov        ah,9
        int        21h

        mov        ah,1                   
        int        21h
        mov        ah,4ch                   
        int        21h
codeseg        ends   
    END START

Tihs is the subprogram:

; Concat- Copies the string pointed at by SI to the string
; rointed at byDI and then concatenates the string;
; pointed at by BX to the destination string.
;
; On entry-
;
; DS:SI- Points at the first source string
; DS:BX- Points at the second source string
; ES:DI- Points at the destination string.
;
; Error condition-
;
; The sum of the lengths of the two strings is greater than 255.
; In this event, the second string will be truncated so that the
; entire string is less than 256 characters in length.
public            concat

dataseg        segment
dataseg        ends

codeseg        segment
    assume    cs:codeseg, ds:dataseg, es:dataseg
    concat    proc far
        mov        ax, dataseg
        mov        ds, ax
        mov        es, ax

        push        si
        push        di
        push        cx
        push        ax
        pushf

        ; Copy the first string to the destination string:
        mov        al,
        mov        cl, al
        mov        ch, 0
        mov        ah, ch
        add        al,         ;Compute the sum of the string's
        adc        ah, 0            ; lengths.
        cmp        ax, 256
        jb        SetNewLength
        mov        ah,         ;Save original string length.
        mov        al, 255        ;Fix string length at 255.
    SetNewLength:
        mov        es:, al            ;Save new string length.
        inc        di            ;Skip over length bytes.
        inc        si
        rep        movsb            ;Copy source1 to dest string.

        ; If the sum of the two strings is too long, the second string
        ; must be truncated.
        mov        cl,         ;Get length of second string.
        cmp        ax, 256
        jb            LengthsAreOK
        mov        cl, ah            ;Compute truncated length.
        neg        cl            ;CL := 256-Length(Str1).
    LengthsAreOK:
        lea si, 1                ;Point at second string and
        ; skip the string length.
        cld
        rep movsb                ;Perform the concatenation.
        popf
        pop ax
        pop cx
        pop di
        pop si
        ret
        concat endp
codeseg            ends
    end            concat

After building, run the exe file, DOS command line window glint and disappeared quickly.
Posted on 2009-04-07 06:14:10 by qlmi
You should open a command prompt window first, then execute your program from there.
It is standard behaviour for Windows to close a console window after the program exits. Your program prints a string, then exits, so Windows will close the console window, and you can't see the output.

If you open a command prompt window first, then run it from there, the window will stay open until you exit the command prompt itself, so you can see the output.
Posted on 2009-04-07 07:12:02 by Scali
Hi, Scali. I have run the EXE file  in command prompt window; but there still isn't any string output on my screen. 

When I search for help about this same question, someone's answer is data segment defination in the subprogram and the main program: both data segment combination type should be PUBLIC or COMMON.
After modified my code, the program works corretly. But this teacher also is't able to give me a logically explanation. 
Posted on 2009-04-08 06:54:09 by qlmi
What exactly did you modify then?
Because as far as I can see, you use a separate data segment, and set the ds register to point to that data segment.
So at first sight, I don't see a problem there.
Posted on 2009-04-08 07:37:53 by Scali
In main program, give the  data segment 'PUBLIC' combination type

dataseg        segment      PUBLIC      
        szMsg1        BYTE      ' Hello World!'
        szMsg        BYTE     '2 1', 13,10,'$'
        iData        BYTE      '123456789012'
        szMsg2       BYTE     ' The Art of Assembly Language Programming',13,10,'$'
dataseg        ends

and in subprogram, also give the data segment 'PUBLIC' combination type

dataseg        segment    PUBLIC
dataseg        ends

Posted on 2009-04-08 23:45:54 by qlmi
I think your answer is here:
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_8/CH08-2.html
The public and stack combine types essentially perform the same operation. They concatenate segments with the same name into a single contiguous segment, just as described earlier.


Because you didn't have public, it didn't combine the two datasegs into a single segment, so I suppose that means that the two pieces of code weren't looking at the same data, so they weren't modifying the same string.
Posted on 2009-04-09 07:32:19 by Scali
Absolutely Correct!
Posted on 2009-04-09 08:45:11 by qlmi