emu8086代码触发8086 16位除法溢出错误,求问题排查
解决emu8086中除法溢出问题并正确判断奇偶性
首先,咱们得先搞清楚你为啥会触发除法溢出——在8086的div指令里,溢出可不是因为除以2这个操作本身,大概率是你对除法指令的使用姿势不对。
先说说除法溢出的根源
8086的除法指令分两种:
- 无符号除法
div:如果是8位除数,被除数默认存在AX里,运算后商存在AL,余数在AH;如果是16位除数,被除数是DX:AX(DX存高16位,AX存低16位),商在AX,余数在DX。 - 有符号除法
idiv:规则和div类似,但处理的是有符号数。
溢出触发的条件是商超出了目标寄存器的范围。比如你用8位除数时,商如果大于0xFF(255),就会溢出;用16位除数时商大于0xFFFF(65535)才会溢出。但除以2怎么会溢出呢?大概率是你错误地把32位的被除数只放到了AX里,或者误用了idiv且被除数是负数导致符号扩展出问题?
更高效且不会溢出的奇偶判断方法
其实判断奇偶根本不需要除法——奇偶性只看数值的最低位:最低位是0就是偶数,是1就是奇数。用位运算比除法快得多,还完全不会有溢出问题,推荐两种写法:
方法1:使用test指令
test指令会按位与两个操作数,但不保存结果,只影响标志位。最低位和1做与运算,结果为0的话ZF(零标志位)会置1,否则置0:
mov ax, your_number ; 把要判断的数放到AX里 test ax, 1 ; 测试最低位 jz even_number ; 如果ZF=1(结果为0),跳转到偶数处理逻辑 ; 这里是奇数处理逻辑 even_number: ; 这里是偶数处理逻辑
方法2:使用and指令
and指令会保存运算结果,你可以直接看结果是否为0:
mov ax, your_number and ax, 1 cmp ax, 0 je even_number ; 奇数逻辑 even_number: ; 偶数逻辑
如果一定要用除法来实现(不推荐,但解决溢出问题)
如果你坚持要用除法,那得确保被除数的格式正确。比如判断16位无符号数的奇偶:
mov ax, your_number ; 被除数在AX mov bl, 2 ; 除数是2(8位) div bl ; 执行除法,商在AL,余数在AH ; 余数AH为0是偶数,为1是奇数 cmp ah, 0 je even_number ; 奇数逻辑 even_number: ; 偶数逻辑
这里用8位除数bl,被除数在AX,除以2的话商最大是0x7FFF(如果AX是0xFFFF),远小于0xFF,绝对不会溢出。如果你之前用的是16位除数(比如div bx),那被除数需要是DX:AX,如果DX不是0,就可能导致商溢出?比如DX里有非零值,除以2后商超过0xFFFF,这时候就会触发溢出。
总结
优先用位运算判断奇偶,既高效又不会有溢出问题;如果非要用除法,一定要严格遵循8086除法指令的寄存器使用规则,确保被除数的格式和除数的位数匹配。
内容的提问来源于stack exchange,提问作者ErTR
相关产品推荐
相关产品推荐

