如何打印 X86-64 程序集中命令行参数的数量?

Ano*_*non 1 assembly stack command-line x86-64

我正在尝试打印 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 
Run Code Online (Sandbox Code Playgroud)

Jes*_*ter 6

你有以下问题(至少):

  1. 该堆栈布局适用于初始入口点,而不是main.
  2. 您正在弹出rbp刚刚推送的内容,而不是堆栈上已有的任何内容。
  3. 您弹出rsp(堆栈指针),稍后它会咬您:push / pop 和 call / ret 指令用作rsp指针。
  4. 虽然也作为参数main获取,但 64 位调用约定不会将其传递到堆栈上。argc
  5. 您尝试在应该传递的时候argc传递,因为它是 的第二个参数。由于是 32 位,您可以使用.rdirsiprintfintesi
  6. printf尝试解释argc为字​​符串,因为您使用的%s是而不是%d格式字符串。
  7. 您不会将%alforprintf归零(这在实践中并不致命,因为它只需要是一个上限,因此其中的任何值都应该在 libc 的非古代版本中工作。较旧的 GCC 计算了间接跳转,因此AL 值高于 8 可能会崩溃.)

可选:您的代码不是位置独立的,这是现代系统中推荐的(有时是必需的)。您可以将格式字符串放入其中,.rodata因为它是只读的。

固定版本可能如下所示:

.globl main
main:
  push %rbp                        # rbp not used, for alignment only

  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
 
  pop %rbp
  ret

.section .rodata
format_string: .string "Arguments: %d\n"
Run Code Online (Sandbox Code Playgroud)