我试图打印x86-64汇编程序中存在的命令行参数的数量。
根据我的理解,参数信息存储在堆栈中。
我觉得我错过了一些关于如何从堆栈中检索存储的项的基本知识,但我不知道确切的内容。
.file "args.s"
.globl main
.type main, @function
.section .data
format_string:
.string "Argument: %s\n"
.section .text
main:
pushq %rbp
movq %rsp, %rbp
popq %rsp ; get argc
movq %rsp, %rdi ; move argc to rdi, first parameter register
movq $format_string, %rdi ; pass in the string to be used and give the parameter
call printf
leave
ret
.size main, .-main
1条答案
按热度按时间mrfwxfqh1#
你有以下问题(至少):
1.该堆栈布局用于初始入口点,而不是
main
。1.你弹出的是你刚刚压入的
rbp
,而不是堆栈上已经存在的任何东西。1.您弹出
rsp
(堆栈指针),稍后它会咬您:push / pop和call / ret指令使用rsp
作为指针。1.虽然
main
也获取argc
作为参数,但64位调用约定不会在堆栈上传递它。1.当
rdi
应该是rsi
时,尝试在rdi
中传递argc
,因为它是printf
的第二个参数。因为int
是32位,所以可以使用esi
。printf
试图将argc
解释为字符串,因为您在格式字符串中使用了%s
而不是%d
。1.对于
printf
,您不需要将%al
置零(这在实践中并不致命,因为它只需要是一个上限,因此在非旧版本的libc中,其中的任何值都应该有效。旧的GCC计算了间接跳跃,因此AL values above 8 could crash。可选:您的代码不是位置独立的,这在现代系统中是推荐的(有时是必需的)。您可以将格式字符串放入
.rodata
,因为它是只读的。一个固定的版本可能看起来像: