x86_64架构下GAS汇编如何比较命令行参数?
问题分析与修正方案
你的代码有三个核心错误导致无法正确匹配命令行参数,以下是具体问题和修正方法:
错误1:错误加载字符串内容而非地址
你写的 movq arg, %rdi 是把 arg 内存地址处的8字节数据加载到 %rdi,但实际上你需要的是 arg 的地址(和 %rsi 里的命令行参数地址对应)。AT&T 语法中,用 $ 表示立即数,所以应该改成:
movq $arg, %rdi # 取arg的地址存入rdi
错误2:用cmpq直接比较地址而非字符串内容
cmpq %rsi, %rdi 只是比较两个寄存器里的地址值,而不是地址指向的字符串内容。要判断两个字符串是否相等,必须调用C标准库的 strcmp 函数:
- 把第一个字符串地址放到
%rdi,第二个放到%rsi - 调用
strcmp后,返回值存在%eax中,返回0表示两个字符串完全相等
错误3:目标字符串缺少终止符
.ascii "-i" 定义的字符串没有null终止符,而命令行参数是C风格的null终止字符串,strcmp 会一直读到内存随机数据,导致比较结果错误。应该改成:
arg: .asciz "-i" # asciz会自动添加null终止符
修正后的完整代码
.text output: .asciz "%s" arg: .asciz "-i" # 修正为带终止符的字符串 .global main main: movq 8(%rsi), %rsi # 获取第一个命令行参数地址(argv[1]) movq $arg, %rdi # 把目标字符串地址存入rdi call strcmp # 调用strcmp比较字符串 testl %eax, %eax # 检查返回值是否为0(相等) je he # 相等则跳转到he标签 movq $0, %rdi call exit he: movq $output, %rdi movq %rsi, %rsi # 将匹配到的参数地址作为printf的第二个参数 movq $0, %rax call printf movq $0, %rdi call exit
额外说明
编译时需要链接C标准库,直接用gcc编译即可:
gcc -o arg_check arg_check.s
运行时输入 ./arg_check -i 就能触发he子程序的输出逻辑。
内容的提问来源于stack exchange,提问作者chiken
相关产品推荐
相关产品推荐

