80386汇编求N长子数组最小值及剩余元素最大值代码排错
80386汇编程序错误排查
代码运行结果不符合预期,核心是3处比较逻辑写反+1处标签冲突问题,具体如下:
- 前N个元素的最小值比较逻辑反向:
lesser分支处理前N-1个元素时,初始al='9'作为最小值初值是正确的,但判断逻辑写反:原代码当al >= digit(当前最小值比新读入数字大)时直接跳走不更新,反而当al < digit时把al更新为更大的数字,实际是在找最大值,完全不符合需求。 - 第N个元素的处理逻辑错误:当计数到第N个元素时,原代码仅当
al >= digit时才跳去保存最小值,否则直接把al更新为更大的digit,破坏了之前计算的最小值结果;且保存最小值的逻辑没有和比较结果绑定,无论是否更新最小值都会直接写入内存,结果不可控。 - 剩余元素的最大值比较逻辑反向:
greater分支处理N之后的元素时,切到al='0'作为最大值初值是正确的,但判断逻辑同样写反:原代码当al <= digit(当前最大值比新读入数字小)时直接跳走不更新,反而当al > digit时把al更新为更小的数字,实际是在找最小值,完全不符合需求。 - 标签冲突隐患:原代码用
end作为跳转标签,而end是MASM汇编器的保留伪指令,用来标记程序段结束,作为自定义标签容易引发汇编错误。
修正后可运行代码
.data? n db ? digit db ? minimum db ? maximum db ? empty dw ? .data messagen1 db "Input untill what array element should we check the minimum of first subarray", 0 messagen2 db "i.e. from what element should maximum value of subarray be checked: ", 0 input db "Input elemnts(digits) of array: ", 0 error db "Entered array is not long enough(It has less than N elements)", 0 message1 db "Minimum of a first subarray is: ", 0 message2 db "and maximum of second subarray is: ", 0 new_line db 13, 10, 0 .code start: mov al, '9' ; 最小值初始化为最大数字字符'9',ASCII顺序和数字大小一致可直接比较 mov bl, '0' ; 计数器从'0'起始,每读一个有效数字inc bl,计数值为对应ASCII数字,可直接和输入的n比较 invoke StdOut, addr messagen1 invoke StdOut, addr new_line invoke StdOut, addr messagen2 invoke StdIn, addr n, 1 invoke StdIn, addr empty, 2 ; 吞掉输入N后的回车换行 invoke StdOut, addr input looping: invoke StdIn, addr digit, 1 invoke StdIn, addr empty, 2 ; 吞掉每个数字输入后的回车 cmp digit, '0' je end_input ; 碰到终止符'0'跳出循环 inc bl cmp bl, n jl lesser ; 未到第N个元素,走最小值比较分支 jg greater ; 过了第N个元素,走最大值比较分支 ; 处理第N个元素:完成最后一次最小值比较后切换到最大值计算模式 cmp al, digit jle save_min ; 当前最小值小于等于新数字,无需更新 mov al, digit ; 新数字更小,更新最小值 save_min: mov minimum, al mov al, '0' ; 最大值初始化为最小数字字符'0' jmp looping lesser: ; 前N个元素找最小值:新数字更小则更新 cmp al, digit jle looping mov al, digit jmp looping greater: ; 剩余元素找最大值:新数字更大则更新 cmp al, digit jge looping mov al, digit jmp looping end_input: cmp bl, n jl err_exit ; 有效元素个数不足N,抛出错误 jge calc_exit err_exit: invoke StdOut, addr error invoke ExitProcess, 1 calc_exit: mov maximum, al invoke StdOut, addr message1 invoke StdOut, addr minimum invoke StdOut, addr new_line invoke StdOut, addr message2 invoke StdOut, addr maximum invoke ExitProcess, 0 end start
测试验证
用给出的用例测试:输入N=4,依次输入3、5、2、6、9、4,最后输入0终止:
- 前4个元素3/5/2/6的最小值为字符'2',正确存入
minimum - 剩余元素9/4的最大值为字符'9',正确存入
maximum - 输出结果和预期完全匹配。
注:当前代码适配「每个数字单独输入后按回车」的交互逻辑,如果需要支持空格分隔的单行输入,调整输入吞字符的逻辑即可。
内容的提问来源于stack exchange,提问作者Danče
相关产品推荐
相关产品推荐

