You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:40:17