增加 rsp 是否等于 pop?

Does incrementing rsp is equal to pop?

我是汇编新手,我想编写一个函数来在汇编中打印数字并从 C++ 中调用它,请参阅下面的代码

cpp:

#include <iostream>
#include <stdint.h>

extern "C" void printunum(uint64_t);

int main()
{
    printunum(12345);
    std::cout<<std::endl;
    return 0;
}

程序集:

   global printunum
section .text
printunum:
   mov rax,rdi
   mov rdi,10
   mov rsi,0

while1:
   cmp  rax,0
   je   endwhile1
   mov  rdx,0
   div  rdi
   inc  rsi
   add  rdx,48
   push rdx
   jmp  while1
endwhile1:

   mov r10,rsi

while2:
   cmp r10,0
   je  endwhile2
   mov rax,1
   mov rdi,1
   mov rsi,rsp  ;to pass memory address 
   add rsp,8    ;it is equal to pop or it is wrong and it will add 8 bytes here?
   mov rdx,1
   syscall
   dec r10
   jmp while2
endwhile2:
   ret

已编辑程序集:

      global print_uint64
section .text
    print_uint64:

   ;init
      mov rax,rdi
      mov rdi,10
      mov rsi,rsp
   ;endinit

   while:
      xor  rdx  ,rdx
      div  rdi
      add  rdx  ,48
      dec  rsi
      mov  [rsi],dl
      cmp  rax  ,0
      je   else 
      if: 
      jmp  while
      else:
   endwhile: 

   ;print
      mov rax,1
      mov rdi,1
      mov rdx,rsp
      sub rdx,rsi
      syscall
   ;endprint 

   ;return
      mov rax,rsp
      sub rax,rsi
      ret

我编译:

srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ nasm -f elf64 asm.asm
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ g++ main.cpp asm.o -o main 
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ ./main
12345
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$

我的处理器 amd64(x86-x64),我正在使用 kali linux

1)上面的代码没有错(pop在x64位机器上等于rsp+8)

2)mul运算将结果放入rdx:rax我如何将它放入单个内存

3)div 操作从 rdx:rax 获取 dividend 我怎样才能将单个值放入 rdx:rax。 感谢您的答复。

POP 所做的是:

  • 将数据从 [RSP] 移动到目标寄存器
  • 将寄存器的大小添加到 RSP

所以如果你不需要实际使用堆栈中的数据,你可以直接将数据的大小添加到RSP,它具有相同的效果

此示例包含对先前评论中的一些建议的修复,并且比您的版本短 24 个字节。此外,一些数学运算已经完成,因为 RBXRDI 之间的差异与在 R10[ 中使用计数器相同=18=].

尽管使用 push 构建字符串是一个新颖的想法,但正如指出的那样,在某些系统上,每个字符的 7 个 NULL 可能会导致问题,而且不仅会造成不必要的大缓冲区。

    global printnum
    section .text

printnum:

; The maximum signed 64 bit value ( 9223372036854775807 ) needs a maximum of 19 digits or
; 20 for unsigned values. Create a buffer on the stack suitably large enough for that.

    push    rbp
    mov     rbp, rsp
    sub     rsp, 32         ; Reserve 32 bytes so stack stays QWORD aligned.

    mov     rax, rdi        ; Move value passed by caller to be converted.
    mov     rdi, rbp        ; Establish pointer to next byte past EOS (End of String).
    mov     ecx, 10         ; Divisor

LtoA:
    xor     edx, edx
    div     rcx
    or       dl, '0'
    dec     rdi             ; This way RDI always points to most recent character written.
    mov     [rdi], dl       ; Essentially DL = RAX % 10.
    test    rax, rax
    jnz     LtoA

showString:
    mov      al, 1          ; Equivalent to SYS_WRITE.
    mov     rsi, rdi        ; RSI points to beginning of string.
    mov     edi, eax        ; Equivalent to STDOUT.
    mov     rdx, rbp
    sub     rdx, rsi        ; Number of byte to be displayed.
    syscall

    leave                
    ret