如何用x86-64 AT&T语法打印数组的每个元素?
问题分析与修复
第一段代码段错误的原因
在x86-64 System V调用约定里,rcx、rsi属于调用者保存寄存器——你调用print_int时,这个函数可能会修改这两个寄存器的值。你的代码调用print_int前没保存rcx(数组地址)和rsi(循环索引)的状态,返回后这俩寄存器的内容被改了,后续访问数组时用了错误的地址或索引,直接触发段错误。
第二段代码的逻辑问题
循环跳转条件写反了:cmpq $5, %rsi之后用je loop,意思是只有当索引等于5时才继续循环。但索引从0开始,第一次加1后变成1,和5不相等,直接跳去exit,只打印了数组第一个元素1,再加上exit里的3,就出现了你看到的13。
修正后的完整代码
解决上述问题,同时遵循调用约定保护寄存器,修正循环逻辑:
.section .data array: .quad 1,2,3,4,5 .section .text .globl main main: # 把rcx和rsi压栈保存,避免被print_int修改 pushq %rcx pushq %rsi leaq array(%rip), %rcx movq $0, %rsi loop_start: # 索引到5就退出循环(数组只有0-4四个有效索引) cmpq $5, %rsi jge loop_end movq (%rcx, %rsi, 8), %rdi callq print_int incq %rsi jmp loop_start loop_end: movq $3, %rdi callq print_int # 恢复之前保存的寄存器 popq %rsi popq %rcx # main函数按约定要返回0,保证程序正常退出 movq $0, %rax ret
重要注意点
- 寄存器保护:调用外部函数前,必须保存好你要继续使用的调用者保存寄存器,这里用栈来暂存
rcx和rsi。 - 循环边界:数组有5个元素,索引范围是0到4,所以当
rsi等于5时必须停止循环。 - main函数返回:按照C调用约定,
main需要返回一个整数值,最后加上movq $0, %rax和ret,避免程序退出状态异常。
内容的提问来源于stack exchange,提问作者chez93
相关产品推荐
相关产品推荐

