AT&T汇编构建输入数字向量报错段错误,求修正方案
AT&T汇编段错误问题排查与修复
问题描述
要将输入数字(1、4、3、5、10)存入向量v,编写的AT&T汇编代码运行时触发“Segmentation fault (core dumped)”错误,以下是原代码:
.data v: .space 128 # 为向量分配的空间 N: .space 4 # 存储单个输入数字 n: .space 4 # 存储输入数字的个数 indexV: .space 4 index: .space 4 formatScanf: .asciz "%ld" formatPrintf: .asciz "%ld " .text .global main main: pushl $n pushl $formatScanf call scanf popl %ebx popl %ebx lea v, %edi movl $0, indexV et_vector: movl indexV, %ecx cmp %ecx, n je et_print pushl $N pushl $formatScanf call scanf popl %ebx popl %ebx movl $N, (%edi, %ecx, 4) incl indexV jmp et_vector movl $0, index et_print: movl index, %ecx cmp %ecx, n je et_exit lea v, %edi movl (%edi, %ecx, 4), %ebx pushl %ebx pushl $formatPrintf call printf popl %ebx popl %ebx pushl $0 call fflush popl %ebx incl index jmp et_print et_exit: movl $1, %eax movl $0, %ebx int $0x80
错误分析与修复点
- 格式符类型不匹配:
%ld是64位长整型格式符,但n、N都是4字节的32位整型变量,scanf会尝试写入8字节数据,直接越界破坏内存,引发段错误。需将formatScanf和formatPrintf的格式符改为%d。 - 错误取N的地址而非值:
movl $N, (%edi, %ecx, 4)中$N是取N的内存地址,不是存储的输入值,应改为movl N, (%edi, %ecx, 4),取N变量里的数值存入向量。 - cmp指令操作数顺序错误:AT&T汇编中
cmp 源, 目的的逻辑是目的 - 源,原代码cmp %ecx, n实际是计算n - %ecx,逻辑上要判断索引%ecx是否等于输入个数n,应改为cmp n, %ecx,相等时跳转至打印逻辑。 - 立即数直接写入内存非法:x86 32位汇编不支持
movl $0, indexV这种直接把立即数存到内存变量的操作,需通过寄存器中转,比如movl $0, %eax; movl %eax, indexV,同理movl $0, index也要做相同修改。
修复后的完整代码
.data v: .space 128 # 为向量分配的空间 N: .space 4 # 存储单个输入数字 n: .space 4 # 存储输入数字的个数 indexV: .space 4 index: .space 4 formatScanf: .asciz "%d" formatPrintf: .asciz "%d " .text .global main main: # 读取输入数字的个数n pushl $n pushl $formatScanf call scanf popl %ebx popl %ebx lea v, %edi # 初始化索引indexV为0 movl $0, %eax movl %eax, indexV et_vector: movl indexV, %ecx # 判断索引是否等于n,相等则跳转打印 cmp n, %ecx je et_print # 读取单个输入数字到N pushl $N pushl $formatScanf call scanf popl %ebx popl %ebx # 将N的值存入向量v的对应位置 movl N, (%edi, %ecx, 4) # 索引自增 incl indexV jmp et_vector et_print: # 初始化打印索引为0 movl $0, %eax movl %eax, index print_loop: movl index, %ecx # 判断打印索引是否等于n,相等则退出 cmp n, %ecx je et_exit lea v, %edi movl (%edi, %ecx, 4), %ebx # 打印当前元素 pushl %ebx pushl $formatPrintf call printf popl %ebx popl %ebx # 刷新输出缓冲区 pushl $0 call fflush popl %ebx # 打印索引自增 incl index jmp print_loop et_exit: # 系统调用退出程序 movl $1, %eax movl $0, %ebx int $0x80
内容的提问来源于stack exchange,提问作者Barzoius Mecca
相关产品推荐
相关产品推荐

