汇编程序求助:判断三数和奇偶性的函数始终返回true
汇编程序判断三数和奇偶性的问题排查与修复
核心问题分析
参数栈顺序完全错误
调用时压栈顺序是push CX → push BX → push AX,栈遵循先进后出规则,栈顶到栈底的实际顺序是AX → BX → CX。但你在oddtest里的弹出顺序是pop AX → pop BX → pop CX,这导致三个变量的值完全错位:原本的value1被赋值给CX,value3被赋值给AX,后续计算的总和完全错误。奇偶判断逻辑存在致命漏洞
用循环减2的方式判断奇偶时,若总和为负数奇数,两次dec(DX)后DX会变得更小(更负),cmp(DX,0)后jg sub_repeat不会触发(仅当有符号数大于0时生效),直接跳出循环且不会命中je even_result,最终无论总和是什么都会进入奇数分支。过程声明与调用方式不匹配
过程声明用了var(传引用),但实际调用时是直接压入寄存器的值(传值),虽然你实际想实现传值,但var的声明会误导汇编器;同时@noframe需要手动处理栈平衡,原程序也未做栈清理。冗余的总和计算
判断奇偶性不需要计算完整总和,只需看三个数的最低位(第0位):奇数最低位为1,偶数为0。三个数的和的奇偶性等价于三个数最低位的异或(或相加后取最低位),逻辑更简单且不会出现溢出问题。
修复后的代码
program Odd_Number; #include( "stdlib.hhf" ); static value1 : int8; value2 : int8; value3 : int8; ; 修改为传值声明,移除@noframe让汇编器自动处理栈帧(更安全) procedure oddtest( val v1 : int8; val v2 : int8; val v3 : int8 ); @nodisplay; begin oddtest; mov(0, DL); ; 取三个数的最低位相加,最终只保留结果的最低位 mov(v1, AL); and(1, AL); ; 仅保留最低位 add(AL, DL); mov(v2, AL); and(1, AL); add(AL, DL); mov(v3, AL); and(1, AL); add(AL, DL); and(1, DL); ; 最终结果:1=奇数,0=偶数 cmp(DL, 1); je is_odd; stdout.put("sumIsOdd returned false!"); jmp done; is_odd: stdout.put("sumIsOdd returned true!"); done: ret(); end oddtest; begin Odd_Number; stdout.put( "Provide value1:" ); stdin.get(value1); stdout.put( "Provide value2:" ); stdin.get(value2); stdout.put( "Provide value3:" ); stdin.get(value3); ; 按过程参数顺序直接压入变量值 push(value3); push(value2); push(value1); call oddtest; end Odd_Number;
优化说明
- 改用
val声明参数(传值),配合移除@noframe,让汇编器自动处理栈帧和返回地址,避免手动操作栈的错误。 - 用位运算直接判断最低位,逻辑高效,同时规避了负数、溢出等边界问题。
- 调用时直接压入变量值,无需先加载到寄存器,简化代码结构。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

