奥普瓯江 发表于 2018-12-9 23:44:51

人造人 发表于 2018-12-9 23:05
我修改过的那两个代码?
弄一个gif(或者其他),把你从编译到运行的过程录下来,我看看

这个就是总是在出错

人造人 发表于 2018-12-10 00:45:35

奥普瓯江 发表于 2018-12-9 23:44
这个就是总是在出错

按照你的方法,我试了一下确实会崩溃
但是用g命令直接执行没有问题,所以我怀疑是堆栈太小了(综合中断考虑),堆栈溢出导致改变了返回地址,中断返回到了错误的地址去执行错误的指令

增加栈空间到512字节后,在我这边t命令也没有问题了

assume cs:code, ds:data;, ds:table, ss:stack

data segment
      dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
      dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
data ends   

stack segment
                ; db 16 dup (0)
                db 512 dup (0)
stack ends

code segment

divdw:                                    ;因为10除以ax dx 所得的商大于16位所以在这里我们用了防止溢的这个除法运算方法列如5937000/10就等于90f24大于16位               
                push bx         ;因为我们下面的程序需要用到bx这个寄存器所以我们bx中的数据先暂时放在栈中
               
                mov cx, 10      ;除数
                push ax         ;被除数低位先进站一会在取出,因为我们先要计算高位
                mov ax, dx      ;被除数高位先传给ax因为除法的计算方式是div、除数,被除数被储存在了ax和dx中;为什么第二次执行到这一步就崩溃呢?
                mov dx, 0         ;这个公式第一次运算dx先归零,因为我们把32位的数分解到两个寄存器当中去了
                div cx            ;一个除法运算
               
                mov bx, ax            ;把ax中的数据暂存到bx中
                pop ax            ;把站中的上面push bx中的数据取出存入到ax数据中进行下一个div计算
                div cx            ;第二个除法运算
               
                mov cx, dx      ;把dx中所得到的余数传给cx储存
                mov dx, bx      ;把bx中储存的高位商储存给dx,现在低位的商已经传给了ax因为div得到的商是传给ax余数传给dx
                pop bx                      ;恢复bx中的数据
                ret
               
year_str:                                                      ;该处为year_str标记处ds = data数据段
                mov ax, word ptr ds:
                add si, 2
                mov dx, word ptr ds:
                add si, 2
                mov bx, 0
                push cx
year_one:
                call divdw                                    ;除法跳转到divdw处这里是解决除法溢出一个一个除法公式因为被除数里面有32位数
                push cx                     ;把divdw中传出的余数压进站中
                inc bx                                                ;bx加一这里的bx加一是因为我们下面还需要从占中取出上面计算的余数这个是用来计数的计算我们一共向站中压入多少余数
                mov cx, ax                                        ;ax在divdw中是用于储存低位商的dx储存的是高位商,cx储存的是余数
                jcxz year_three             ;如果低位商储存等于零那我们就跳转到year_three标记处
                jmp short year_one                        ;无条件跳转到year_one标记处
year_three:
                mov cx, bx                  ;上面我们用了bx作为计数,记录divdw被执行了几次cx向站中传输了几次数据已被下面输出用
year_four:
                pop ax                      ;把站中的divdw所用到的余数取出到ax中
               
               
               
                add      ax, '0'                ; 把数字变成字符
               
               
               
                mov ah, 2                   ;ah中储存的是输出时所拥有的属性2代表着绿色字体
                mov byte ptr es:, al;把al数据输出到0b800h段中该段是显存段每行160个字节
                mov byte ptr es:, ah;这是他的属性
                add di, 2                        
                loop year_four
               
                mov di, 0
                add bp, 160
                pop cx
                loop year_str
               
               
                ret                ; 忘了返回
               
               
               
start:      
                mov ax, data
                mov ds, ax
                mov ax, 0b800h
                mov es, ax
                mov ax, stack
                mov ss, ax
                ; mov sp, 16
                mov sp, 512
                mov cx, 3
                mov di, 0
                mov si, 0
               
               
                xor      bp, bp      ; 这个忘了清零
               
               
               
                call year_str    ;跳转到year_str标记处
               

                mov ax, 4c00h
                int 21h
      
               
code ends
end start

奥普瓯江 发表于 2018-12-10 02:02:06

人造人 发表于 2018-12-10 00:45
按照你的方法,我试了一下确实会崩溃
但是用g命令直接执行没有问题,所以我怀疑是堆栈太小了(综合中断 ...

谢谢我把那个栈改大了但是还是出现这种问题用不了t向下执行但是可以用G向下执行,现在我知道我这个程序逻辑正确了就行,别的问题因为接触汇编的时间还短慢慢向下学吧,希望以后能解答,再次说声谢谢这么晚还帮我回答我替,十分感谢,麻烦了,下面是gif
这个是用G执行的是可以执行出来数字

但是这个用t执行的确不行不知道为什么先这样吧,谢谢您了,谢谢您的帮助

assume cs:code, ds:data;, ds:table, ss:stack

data segment
      dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
      dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
data ends   

stack segment
                db 512 dup (0)
stack ends

code segment

divdw:                                      ;因为10除以ax dx 所得的商大于16位所以在这里我们用了防止溢的这个除法运算方法列如5937000/10就等于90f24大于16位               
                push bx         ;因为我们下面的程序需要用到bx这个寄存器所以我们bx中的数据先暂时放在栈中
               
                mov cx, 10      ;除数
                push ax         ;被除数低位先进站一会在取出,因为我们先要计算高位
                mov ax, dx      ;被除数高位先传给ax因为除法的计算方式是div、除数,被除数被储存在了ax和dx中;为什么第二次执行到这一步就崩溃呢?
                mov dx, 0         ;这个公式第一次运算dx先归零,因为我们把32位的数分解到两个寄存器当中去了
                div cx            ;一个除法运算
               
                mov bx, ax          ;把ax中的数据暂存到bx中
                pop ax            ;把站中的上面push bx中的数据取出存入到ax数据中进行下一个div计算
                div cx            ;第二个除法运算
                mov cx, dx      ;把dx中所得到的余数传给cx储存
                mov dx, bx      ;把bx中储存的高位商储存给dx,现在低位的商已经传给了ax因为div得到的商是传给ax余数传给dx
                pop bx                      ;恢复bx中的数据
                ret
               
year_str:                                                        ;该处为year_str标记处ds = data数据段
                mov ax, word ptr ds:
                add si, 2
                mov dx, word ptr ds:
                add si, 2
                mov bx, 0
                push cx
year_one:
                call divdw                                 ;除法跳转到divdw处这里是解决除法溢出一个一个除法公式因为被除数里面有32位数
                add cx, '0'
                push cx                     ;把divdw中传出的余数压进站中
                inc bx                                                ;bx加一这里的bx加一是因为我们下面还需要从占中取出上面计算的余数这个是用来计数的计算我们一共向站中压入多少余数
                mov cx, ax                                        ;ax在divdw中是用于储存低位商的dx储存的是高位商,cx储存的是余数
                jcxz year_three             ;如果低位商储存等于零那我们就跳转到year_three标记处
                jmp short year_one                        ;无条件跳转到year_one标记处
year_three:
                mov cx, bx                  ;上面我们用了bx作为计数,记录divdw被执行了几次cx向站中传输了几次数据已被下面输出用
year_four:
                pop ax                      ;把站中的divdw所用到的余数取出到ax中
                mov ah, 2                   ;ah中储存的是输出时所拥有的属性2代表着绿色字体
                mov byte ptr es:, al;把al数据输出到0b800h段中该段是显存段每行160个字节
                mov byte ptr es:, ah;这是他的属性
                add di, 2                        
                loop year_four
               
                mov di, 0
                add bp, 160
                pop cx
                loop year_str
                ret
start:       
                mov ax, data
                mov ds, ax
                mov ax, 0b800h
                mov es, ax
                mov ax, stack
                mov ss, ax
                mov sp, 16
                mov cx, 21
                mov bp, 480
                mov di, 0
                mov si, 0
                call year_str    ;跳转到year_str标记处
               

                mov ax, 4c00h
                int 21h
       
               
code ends
end start

tianyuan 发表于 2018-12-10 11:22:22

本帖最后由 tianyuan 于 2018-12-10 11:42 编辑

我用人造人改后的代码没问题 单步跟综-t没有崩溃,难道是环境的原因   我用DOSBox

tianyuan 发表于 2018-12-10 12:17:43

assume伪指令把栈给注释掉了,看看你link时有没有出现 waering L4021: no stack segment

人造人 发表于 2018-12-10 12:37:12

看,我发现了什么!

tianyuan 发表于 2018-12-10 13:34:59

本帖最后由 tianyuan 于 2018-12-10 13:37 编辑

人造人 发表于 2018-12-10 12:37
看,我发现了什么!

{:10_250:}{:10_247:}

奥普瓯江 发表于 2018-12-10 14:38:19

人造人 发表于 2018-12-10 12:37
看,我发现了什么!

{:9_230:}哎就是他的问题,是我错了改过来就行了{:9_232:}
页: 1 [2]
查看完整版本: 为什么总是崩溃能这只是一个简单的mov ax, dx