微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

了解汇编、nasm、x86 中的 printf 函数我不知道为什么这段代码没有打印出任何东西

如何解决了解汇编、nasm、x86 中的 printf 函数我不知道为什么这段代码没有打印出任何东西

BITS 64;

          global    main
          extern    printf

          section   .text
main:                                       ; This is called by the C library startup code
          push      rbx                     ; required to make printf 16-byte aligned.
                                            ; For Now we only do this once!
          
          push      qword 300
          call      sum 

          mov       rdi,dfmt               ; set 1st parameter (format)
          mov       rsi,rax                  ; set 2nd parameter (low byte)
          xor       rax,rax                ; because printf is varargs we must clear rax
          call      printf                  ; printf(format,current_number)

          pop       rbx                     ; must restore rbx for Linux
          ret                               ; Return from main back into C library wrapper

sum:
      push      rbp                     ; retrieve parameter
          push      rbx                     ; save prevIoUs 
          mov       rbp,rsp
          add       rsp,24                 ; create room for integer
          mov       rbx,[rbp]              ; rbx = param
            
          cmp       rbx,0                  ; if (n <= 0)
          je        base                 
          
          dec       rbx                     ; decrement rbx to place in stack
          push      rbx                     ; put (rbx - 1) in stack
          inc       rbx
          call      sum                     ; calculate sum(n - 1)
          add       rax,rbx     
          pop       rbx 
          
          jmp end
          base:
          mov       rax,1
          
          end:
          pop       rbx
          pop       rbp
          ret
           
dfmt:
          db  "%ld",10,0

解决方法

让我们一点一点地经历这个。

main 函数中,您有 push qword 300。我认为这是为了将参数传递给 sum?如果是这样......那不是你在做什么。我建议改为遵循 AMD64 调用约定并使用 mov rdi,300 然后使用 call sum,这会期望在 rdi 中找到它的第一个参数。

无论如何,在 sum 中,您要做的第一件事是 push rbp,这是非常标准的。那么你push rbx。这是一个被调用者保存的寄存器,很好。然后是 mov rbp,rsp,这也是非常标准的。

现在你释放一些带有add rsp,24的堆栈,我不明白。堆栈向低地址增长,因此要保留一些堆栈,您可以从 rsp减去。但也许这不是你在做什么?

现在我真的很困惑。您执行 mov rbx,[rbp],但由于 rbp 没有被 main 函数修改,因此它不会指向我们想要的任何位置。我只能假设这是在堆栈上获取参数的一些尝试?

老实说,在这一点上我很难过。

通常使用以下样板启动您的函数。

push rbp
mov rbp,rsp

原因是为了保护栈。现在所有引用都可以针对 rbp 完成,它在您的代码中永远不会改变(它总是指向您的堆栈帧)。它是一个被调用者保存的寄存器,所以无论如何我们都必须保存它,并在设置它之前在堆栈上这样做。

通常使用以下样板结束您的函数。

mov rsp,rbp
pop rbp
ret

按照 AMD64 调用约定的要求,这会将堆栈指针和 rbp 恢复到它们在入口时的位置。这有一个同义词:leave。下面的代码是等价的。

leave
ret

现在,当您使用 printf(或任何可能使用 xmm 寄存器的函数)时,您还必须确保在调用之前堆栈在 16 字节边界上对齐。您可以假设堆栈在进入 main 时对齐。 push rbp 会将它搞砸(减少 8 位),但是当您执行 call printf 时,您将再推 8 个字节(返回地址)并加速!堆栈已对齐。

我最后的建议是使用 AMD64 调用约定而不是使用堆栈。将参数放入rdi,获取rax中的返回值。

如果不知道您要做什么,我无法提供更多帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。