王爽汇编书上一段程序的调试有关问题,高手指教!

王爽汇编书上一段程序的调试问题,高手指教!!!!!!!!
看到王爽老师书的第十章有如下程序:

assume   cs:code,ds:data,ss:stack
data   segment
db   'word ',0
db   'unix ',0
db   'wind ',0
db   'good ',0
db   '00000 '
data   ends

stack   segment
dw   0,0,0,0
stack   ends

code   segment
start:mov   ax,data
            mov   ds,ax
            mov   bx,0
            mov   cx,4
            mov   ax,stack
            mov   ss,ax
            mov   sp,4
        s:mov   si,bx
            call   capital
            add   bx,5
            loop   s

            mov   ax,4c00h
            int   21h

capital:push   cx
                push   si
                mov   cl,[si]
                mov   ch,0
                jcxz   ok
                and   byte   ptr   [si],11011111b
                inc   si
                jmp   short   capital
          ok:pop   si
                pop   cx
                ret
code   ends
end   start

每次执行到要跳转时(call)就出现ntvdm那个错误,感觉好像是压栈出了问题,不过不知是怎么的问题,感觉又没错,不知是怎么回事,大家指点一下。
谢谢了!!!!!!!!!

还有就是不两个push和pop从子程序里没拿到外面时是能执行的,而且是正确的,但是我明明在堆栈段定义的是4个word空间,为什么执行时ss=0b98,cs=0b99呢,是不是一个段最小就是16个字节呀?指教了,谢谢!!!!!!!!!!!


------解决方案--------------------
授之以鱼,不如授之以渔。没有自己的调试技术,就不能自立!
对子过程调用、返回,以及其它入栈、出栈操作的解决之道:
实时跟踪堆栈和相关寄存器的值,一定能够找到错误的所在。
------解决方案--------------------
这很简单自己调一下啊

------解决方案--------------------
LZ认为一个段还能比16个字节更小吗?
------解决方案--------------------
8086系统,一个段最小可以有多小,最大可以有多大?
后者好像经常有提及,就是:一个段最大是64K,因为这是由偏移地址的大小决定的,偏移地址最大值又受到sp,ip,di,si,bx,bp这些寄存器的位数限制,很容易知道是64K。前者好像任何一本书里都没有讲过,但是仍旧很简单,段的位置是由段值和偏移构成的。偏移只决定段的最大值,虽然偏移可以任意小,但段的最小值仍是由段值确定的,书上说段的起始地址必须是16的倍数,如此一来,只要两个段不是重叠的,即便挨得再近,也小不过16字节,所以段的最小值就是16字节。