修复SIGSEGV后汇编程序无限运行无控制台输出求助
问题分析与修复方案
你的代码存在两个核心问题:输出系统调用参数错误,以及位操作逻辑冗余(不影响循环终止但可优化),以下是具体分析和修复:
1. 输出失败的根本原因:Write系统调用参数错误
Linux int 0x80 系统调用中,eax=4 对应的write接口要求ecx必须是指向输出数据的内存地址,而非直接传递字符的ASCII值。你当前用movzx ecx,al把ASCII字符值直接存入ecx,会导致系统调用尝试访问以该字符值为地址的内存(比如字符'0'对应地址0x30,属于无效用户空间地址),触发访问错误,因此没有任何输出。
2. 循环逻辑的冗余(可简化)
你当前的位操作中,shr bl,cl是多余的——因为每次循环都会用mov eax,edi恢复原始值,bl其实可以每次循环重新初始化为1,避免不必要的移位操作。
修复后的完整代码
SECTION .data linefeed db 0xA,0xD char_buf db 0 ; 新增临时缓冲区,用于存储要输出的ASCII字符 SECTION .bss SECTION .text global _start _start: ; 调用sys_time获取当前秒数(eax=13,返回值存在eax) mov eax,13 int 80h mov edi,eax ; 保存原始时间值到edi mov bl,1 mov cl,0 bitmaska: shl bl,cl ; 生成第cl位的掩码(1 << cl) and al,bl ; 保留al的第cl位 shr al,cl ; 将该位移到最低位,al变为0或1 add al,48 ; 转换为ASCII字符(0→48,1→49) ; 修复write调用:将字符存入缓冲区,再传递缓冲区地址给ecx mov [char_buf], al mov edx,1 mov ecx, char_buf ; ecx指向存储字符的内存地址 mov ebx,1 ; stdout文件描述符 mov eax,4 ; sys_write系统调用号 int 80h mov eax,edi ; 恢复原始时间值到eax inc cl cmp cl,8 jnz bitmaska ; 循环8次,处理AL的8个位 konec: ; 输出换行(注意linefeed是两个字节,edx设为2) mov edx,2 mov ecx,linefeed mov ebx,1 mov eax,4 int 80h ; 退出程序 mov ebx,0 mov eax,1 int 80h
额外优化点
位操作逻辑可以进一步简化,用test和setz指令替代多次移位,让代码更清晰:
bitmaska: mov bl, 1 shl bl, cl test al, bl ; 测试第cl位是否为1 setz al ; 若该位为0,al=0;否则al=1 add al, 48 ; 后续输出逻辑不变
内容的提问来源于stack exchange,提问作者IlikeAssemblyButIsuck-sorry
相关产品推荐
相关产品推荐

