Увеличивает ли rsp значение pop? - PullRequest
0 голосов
/ 14 апреля 2020

Я новичок в сборке. Я хочу написать функцию для печати номера в сборке и вызвать ее из 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 равен rsp + 8 на 64-битной машине).

2) операция mul помещает результат в rdx: rax, как я могу его получить в одну память

3) Операция div получает дивиденды от rdx: rax Как я могу поместить одно значение в rdx: rax. Спасибо за ваш ответ.

Ответы [ 2 ]

3 голосов
/ 14 апреля 2020

Что POP делает:

  • перемещает данные из [RSP] в целевой регистр
  • добавляет размер регистра к RSP

Так что, если вам не нужно фактически использовать данные в стеке, вы можете просто добавить размер данных к RSP, и он будет иметь тот же эффект

2 голосов
/ 14 апреля 2020

В этом примере есть исправления, предложенные в некоторых предыдущих комментариях, и на 24 байта короче, чем ваша версия. Также некоторые математические операции уже выполнены, поскольку разница между RBX и RDI такая же, как при использовании счетчика в R10 .

Хотя построение строки с использованием pu sh является новой идеей, но, как отмечалось, в некоторых системах 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
...