Author Topic: Printing numbers with stack as variable  (Read 770 times)

Offline andyz74

  • Jr. Member
  • *
  • Posts: 18
Printing numbers with stack as variable
« on: December 29, 2024, 11:34:50 AM »
Hello all, I hope you enjoy winter-holidays! :-)

But now to my problem :
I use Linux 64 bit, and my wish is to print numbers on the screen just by syscall, no extern funtions and no extra variables for storing numbers.  Therefore, I use the common way, push every number to stack to get it later and print.
I know, the syscall to write is with rax=1, rdi=1 to use my screen, rsi as pointer to the adress where my string/number is, and rdx for length of string (in my case 1).
As you can see, I use the stackadress in rsi to get my number, and it works with 8 added or 16 added, but not with the common rsp-adress.
Has anybody of you an idea, what is going wrong ? 

Greetz, and thanks in advance, Andy



Code: [Select]
[bits 64]

SECTION .data
    n: dd 1234

global _start

SECTION .text

    _start:

  mov rax, [n]
  xor rcx, rcx       

.loop:
  mov rbx, 10
  xor rdx, rdx
  div rbx            ; Divide RAX by 10
  add rdx, 30h
  push rdx   ; pop Restzahl auf Stack
  inc rcx
  test rax, rax
  jnz .loop

.loop2:
  mov rax, 1         ; Write system call
  mov rdi, 1         ; STDOUT
  xor rsi, rsi
  mov r10, rsp
  add r10, 0 ; change offset to be read in stack 0, 8 or 16
  mov rsi, r10
  pop r12
  mov rdx, 1 ; ein Zeichen schreiben.
  push rcx
  syscall
  pop rcx
  dec rcx
  test rcx, rcx
  jnz .loop2


   mov rax, 1
   mov rbx, 0
   int 0x80



Offline fredericopissarra

  • Full Member
  • **
  • Posts: 376
  • Country: br
Re: Printing numbers with stack as variable
« Reply #1 on: December 29, 2024, 12:52:05 PM »
For your study:
Code: [Select]
  bits  64
  default rel

  section .rodata

nl:
  db  `\n`

  section .text

  global _start

  align 4
_start:
  sub   rsp,8               ; Align RSP to DQWORD (SysV ABI)

  mov   rdi,12345678        ; # to print.
  call  printUint64Decimal

  ; Print a newline
  mov   eax,1
  mov   edi,eax
  mov   edx,eax
  lea   rsi,[nl]
  syscall

  sub   rsp,8               ; restore RSP

  ; Exit program
  mov   eax,60
  xor   edi,edi
  syscall                   ; This syscall never returns.

; Entry RDI = #
  align 4
printUint64Decimal:
  ; Allocate 24 bytes, realigning RSP to DQWORD (SysV ABI).
  ; We just need 22 bytes in the buffer allocated on the stack.
  sub rsp, 24

  mov r9, rsp
  mov rsi, rsp

  mov r8, 0xcccccccccccccccd      ; 1/10, scaled (0b0.00011001100... rounded and shifted left by 67).

  align 4
.loop:
  mov rax, rdi
  dec rsi

  ; Multiply by scaled 1/10, instead of dividing by 10
  ; This is faster.
  mul r8
  mov rax, rdi
  shr rdx, 3                      ; RDX = quotient

  lea rcx, [rdx+rdx*4]            ; RCX = RDX*10
  add rcx, rcx
  sub rax, rcx                    ; RAX = Dividend - RCX (remainder)
  ; RAX = remainder, RDI = quotient

  ; Store remainder converted to ASCII.
  add al, '0'
  mov [rsi], al

  mov rax, rdi
  mov rdi, rdx

  ; Stay in loop if quotient > 9.
  cmp rax, 9
  ja  .loop

  ; Print the buffer, calculating the size of the string.
  mov eax, 1
  mov rdx, r9
  sub rdx, rsi
  mov edi, eax
  syscall

  add rsp, 24
  ret

Offline andyz74

  • Jr. Member
  • *
  • Posts: 18
Re: Printing numbers with stack as variable
« Reply #2 on: December 29, 2024, 03:15:01 PM »
Many thanks Frederico!

At least I have a working example of printing by stack. Would have been happy to know, why mine does not work es expected, but I can live with your variante good. :-)

Thanks ! :-)

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 376
  • Country: br
Re: Printing numbers with stack as variable
« Reply #3 on: December 29, 2024, 05:40:49 PM »
Would have been happy to know, why mine does not work es expected
To push QWORDs with each character calculated in the first loop is a huge waste of stack space. It is simplier to pre-alocate the space (10 chars for a DWORD converted in decimal string), but keeping RSP QWORD (or DQWORD) aligned.

Here's your code modified:
Code: [Select]
  bits  64
  default rel

  section .text

  global _start
_start:
  sub   rsp,8+16      ; Align by DQWORD and reserve space to the string.
                      ; We only need 11 bytes allocated, but we need to keep
                      ; RSP aligned.
                      ;
                      ; Don't really need to keep RSP aligned to DQWORD in this
                      ; code, but it is a good practice in case we use SSE/SSE2.

  mov   rsi,rsp       ; Using RSI because sys_write needs it.

  mov   eax, 1234     ; # to print.
  xor   ecx, ecx      ; Counter = 0.

  mov   byte [rsi],`\n`
  mov   ebx, 10

  align 4
.loop:
  dec   rsi
  xor   edx, edx
  div   ebx     
  add   dl, '0'

  mov   [rsi],dl

  inc   rcx           ; Increment counter.
  test  eax, eax      ; Quotient == 0?
  jnz   .loop         ; No, stay in the loop.

  ; sys_write.
  mov   eax,1
  mov   edi,eax
  lea   edx,[rcx+1]   ; The final '\n' as well.
  syscall

  add   rsp,8+16      ; Restore RSP to its original position.
                      ; Not really needed since sys_exit will not return.

  ; FIXED: Use 'syscall', not 'int 0x80'.
  mov   eax, 60
  xor   edi, edi
  syscall

Offline andyz74

  • Jr. Member
  • *
  • Posts: 18
Re: Printing numbers with stack as variable
« Reply #4 on: December 29, 2024, 07:25:27 PM »
Many many thanks, I will check this as soon as I will be back at my Computer. Many thanks!