代码之家  ›  专栏  ›  技术社区  ›  Anon

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

  •  0
  • Anon  · 技术社区  · 2 年前

    我试图打印x86-64中程序集程序中存在的命令行参数的数量。

    根据我的理解,参数信息存储在堆栈中。

    我觉得我错过了一些关于如何从堆栈中检索存储项的基本知识,但我不知道具体是什么。

    enter image description here

    .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 回复  |  直到 2 年前
        1
  •  5
  •   Peter Cordes    2 年前

    您至少有以下问题:

    1. 堆栈布局用于初始入口点,而不是 main
    2. 你正在弹出 rbp 你只是推了一下,堆栈上没有任何东西。
    3. 你突然进入 rsp (堆栈指针),稍后会咬到你:push/pop和call/ret指令使用 rsp 作为指针。
    4. 虽然 主要的 也得到 argc 作为一个参数,64位调用约定不会在堆栈上传递它。
    5. 你试图通过 argc 在里面 rdi 应该在什么时候 rsi 因为这是的第二个论点 printf 自从 int 是32位,您可以使用 esi
    6. 输出函数 试图解释 argc 作为字符串,因为您使用 %s 而不是 %d 在格式字符串中。
    7. 你不归零 %al 对于 输出函数 (这在实践中并不致命,因为它只需要是一个上界,所以在非古代版本的libc中,其中的任何值都应该有效。旧的GCC计算了一个间接跳跃,所以 AL values above 8 could crash .)

    可选:您的代码与位置无关,这在现代系统中是推荐的(有时也是必需的)。您可以将格式字符串放入 .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"