我想在x86-64汇编中打印出命令行参数(使用AT&T语法)。
这是我上一篇关于如何简单地访问这些参数的文章的后续问题。我还想知道如何将所有命令行参数打印到控制台。
.globl main
main:
push %rbp # rbp not used, for alignment only
mov %rsp, %rbp
mov %edi, %esi # move argc to second parameter register
lea format_string(%rip), %rdi # the format string is the first parameter
xor %eax, %eax # 0 xmm registers used
call printf@plt
xor %eax, %eax # return 0 to behave nicely
mov 16(%rbp), %rsi # get argv[1] (pointer to first command line argument)
mov (%rsi), %rdi # load the pointer to the first argument into %rdi
lea arg_format(%rip), %rsi # load argument format string
xor %eax, %eax # 0 xmm registers used
call printf@plt
pop %rbp
ret
.section .rodata
format_string: .string "Arguments: %d\n"
arg_format: .string "First Argument: %s\n"
1条答案
按热度按时间hpcdzsge1#
你试图从
16(%rbp)
得到argv
,这是没有意义的。不在堆栈上。它是main
的第二个参数,因此在进入函数时它就在%rsi
中。由于
%rsi
是call-clobbered,我们需要在第一个printf
调用中将其保存在调用保留寄存器中。我选择了下面的%rbx
(%rbp
也可以工作)。由于它是调用保留的,我们需要在main
函数的开始和结束时保存和恢复它(这也是为了处理堆栈对齐)。由于
%rbx
指向argv
向量的开始,或者换句话说,它的第零个元素argv[0]
,我们必须加上8来指向argv[1]
。所以mov 8(%rbx), %rsi
会帮我们得到它。此外,您的代码在第二次调用
printf
时颠倒了参数顺序。下面是一个适合我的固定版本:
如果你想打印所有的参数,那么你需要写一个循环。您可以在每次迭代时向
%rbx
添加8,以指向argv
的下一个元素。将其加载到寄存器中,测试其是否为零(即空指针),否则有条件地跳出循环;否则打印出来。我将把实现留给您作为实践。