VS MASM调试found子程序ret返回Source option not available错
报错根因
Source option not available是调试器检测到程序跳转到了无对应调试符号的非法地址时触发的提示,核心原因是栈失衡导致返回地址错误,你的代码存在三个致命问题:
- 直接用
js条件跳转指令进入found子例程,没有通过call指令调用。x86体系下call执行时会自动把下一条指令的地址压栈作为返回地址,ret指令才能正确弹栈回到调用点;直接跳转进入子例程时,栈顶根本没有存入合法返回地址,执行ret时会把栈上的随机垃圾值当成目标地址弹出,直接导致程序跑飞。同样的问题也存在于jns notfound的跳转逻辑里。 - 数组步进长度写错:你定义的
slist元素是SWORD类型(16位有符号整数,占2字节),代码里硬编码add esi,4每次步进4字节,会直接跳过一半数组元素,还会触发越界内存读取。 - 流程断裂:哪怕
ret能正常返回,found/notfound执行完后也没有衔接退出逻辑,会继续执行后续内存里的非法指令。
修复方案
练习标志位跳转的场景下,完全没必要把找到/没找到的逻辑拆成独立子例程用ret返回,直接用普通跳转串起流程即可,从根源上避免栈平衡问题,修复后的完整代码如下:
; chapter -06 ; find first negative number .386 .model flat,stdcall .stack 4096 .data slist SWORD 0,1,2,3,-9,10,20 ExitProcess PROTO,dwExitCode:DWORD .code main PROC mov ecx,LENGTHOF slist mov esi,OFFSET slist mov ebx,0 L1: test WORD PTR [esi], 8000h ; 直接检查16位有符号数的最高位(符号位),不额外改动寄存器 js found add esi, TYPE slist ; 用TYPE关键字自动获取SWORD的字节长度,避免硬编码错误 LOOP L1 jmp notfound ; 循环遍历完未找到负数,跳转对应逻辑 found: mov bx,[esi] ; 把找到的首个负数存入ebx jmp exit_prog notfound: mov ebx,0 ; 未找到时ebx置0 exit_prog: INVOKE ExitProcess,0 main endp end main
额外优化提示
- 你原本写的
pushfd/popfd是多余操作:js判断完成后,只有当前数非负数才会走到步进数组的逻辑,此时已经不需要保留之前的标志位状态,多余的栈操作反而会增加栈失衡的风险。 - 检查符号不需要用
add ax,[esi]的方式,test指令直接按位与检查符号位即可,既不用提前给eax清零,也不会改动源操作数,执行效率更高。
内容的提问来源于stack exchange,提问作者Hackaholic
相关产品推荐
相关产品推荐

