ASM printf prints garbage/segfaults [duplicate] - linux

This question already has answers here:
glibc scanf Segmentation faults when called from a function that doesn't align RSP
(1 answer)
What registers are preserved through a linux x86-64 function call
(3 answers)
Printing floating point numbers from x86-64 seems to require %rbp to be saved
(1 answer)
Why does printf still work with RAX lower than the number of FP args in XMM registers?
(1 answer)
Why does eax contain the number of vector parameters?
(1 answer)
Closed 6 days ago.
I have been trying to call printf from x64 asm, but it prints garbage
Here is the code:
;print all fib numbers from 0 until 100
global main
extern printf
;printf notes
;mov al 0 is neccesary
;rdi: format string
;rsi, rdx, r8... args
section .text
main:
mov r8, 0 ;counter
mov r9, 0 ;nth value
mov r10, 1;n + 1 value
mov al, 0
Loop:
mov rsi, r9
mov rdx, r10
mov rdi, format_str
call printf
mov r11, r10
add r10, r9
mov r9, r11
inc r8
cmp r8, 100
jl Loop
mov rax, 60
mov rdi, 0
syscall
section .rodata
format_str: db "%3d: %30d\\n", 0
Note the mov al. If it is inside the loop, the program prints garbage. But if it is outside the loop, then the program segfaults.
I compile with gcc and I simply want it to output as it would if it were called from c

Related

NASM iterate over string and stop when finds certain value [duplicate]

This question already has answers here:
Garbage in string output function
(1 answer)
can't compare user input with number, nasm elf64
(2 answers)
Closed 3 years ago.
This question is similar to others, but it is not a duplicate. I am learning NASM (assembly).
My program has the following goal. I give as input a word (e.g "aab"). I want to compare each char in the string to a predefined value.
Here is a snippet.
;try to compare
xor rax,rax ;set iteration index to 0
lea rsi, [userpass]
back_to_loop:
cmp rsi, 'a'
je _exit
inc rsi ;increase index
jmp back_to_loop
!!!A good help would be editing the program in such a way, that the iteration would stop as soon as it finds an 'a' in the string. If I found how that is done, I could modify it to my own needs.
My entire effort so far:
section .text
global _start
_start:
;read input
xor rax, rax
mov rdi, rax
mov rsi, userpass
mov rdx, rax
add rdx, 0x64 ; 100
syscall
;try to compare
xor rax,rax ;set iteration index to 0
lea rsi, [userpass]
back_to_loop:
cmp rsi, 'a'
je _exit
inc rsi ;increase index
jmp back_to_loop
_exit:
mov rax, 1
xor rbx, rbx
int 80h
section .bss
num resb 64
section .data
userpass times 100 db 0 ;input

Loop exiting early when making Linux system calls [duplicate]

This question already has answers here:
Why do x86-64 Linux system calls modify RCX, and what does the value mean?
(1 answer)
What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64
(4 answers)
Closed 5 years ago.
I am trying to write a program that prints an integer, the integer is stored in rax register, I don't know why it only prints the first digit of the integer, in this case it's 3.
The program divides rax by 10 and stores the remainder+48 in the reserved memory to display it later. we repeat this as long as rax is different than 0.
code:
section .bss
integer resb 100
section .text
global _start
_start:
mov rax, 321
call _printRAX
mov rax, 60
mov rdi, 0
syscall
_printRAX:
mov rbx, 10
mov rcx, integer
mov [rcx], rbx
_loop1:
inc rcx
mov rdx, 0
div rbx
add rdx, 48
mov [rcx], dl
cmp rax, 0
jne _loop1
_loop2:
mov rax, 1
mov rdi, 1
mov rsi, rcx
mov rdx, 1
syscall
dec rcx
cmp rcx, integer
jge _loop2
ret
output:
3
Try It Online

Displaying a number in x86-64 assembly with only Linux system calls [duplicate]

This question already has answers here:
Why should EDX be 0 before using the DIV instruction?
(2 answers)
How do I print an integer in Assembly Level Programming without printf from the c library? (itoa, integer to decimal ASCII string)
(5 answers)
Closed 2 years ago.
Previous version of this question (that question originally had a different problem, even though the code there is now the same as the code in this question)
I am trying to make code to display a number on console in Linux 64 bit NASM, without the use of c/c++ functions (pure assembly). The code compiles and links fine but it will not give output...
It displays just newline for some time and then displays '7' forever. I am new to Assembly so I don't know what is wrong. Please help... Here is the code:
section .data
num: dq 102 ;my default number to get the reverse of (for now)
nl: db 0x0a
nlsize: equ $-nl
ten: dq 10
section .bss
rem: resq 1
remsize: equ $-rem
section .text
global _start
_start:
cmp qword [num], 0
jng _exit ;jump to _exit if num is not greater than 0
mov rax, [num] ;move the number to rax
mov rbx, [num] ;move the number to rbx as well so that i have original number in register to subtract and get the remainder
mov rcx, [ten] ;move 10 to rcx to be the divisor
div rcx ;divide number in rax by 10
mov [num], rax ;get the quotient to get the remaining number for quotient
mul rcx ;multiply number in rax by 10
sub rbx, rax ;subtract rbx - rax and store the value in rax (right?)
mov [rem], rbx ;get the remainder from rax. this must be done right after div (WHY??????????)
call _disprem ;call _disprem to display the remainder... call returns the flow back to the caller right?
jmp _start ;get to the loop again
_exit:
mov rax, 60
mov rdi, 0
syscall
_newl:
mov rax, 1
mov rdi, 1
mov rsi, nl
mov rdx, nlsize
syscall
ret
_disprem:
mov rax, 1
mov rdi, 1
add qword [rem], 0x0000000000000030 ;since the rem variable is quadword (64 bit)
mov rsi, rem ;for getting ascii value (48 is ascii 0 in decimal) to convert the rem to character
mov rdx, remsize
syscall
sub qword[rem], 0x0000000000000030 ;get me my original number back plz thanks
call _newl
ret

Displaying a number - assembly code not working Linux, x64 (NASM) [duplicate]

This question already has answers here:
Displaying a number in x86-64 assembly with only Linux system calls [duplicate]
How do I print an integer in Assembly Level Programming without printf from the c library? (itoa, integer to decimal ASCII string)
(5 answers)
Closed 2 years ago.
I am learning assembly on Linux (NASM) x64 machine (I don't have access to 32 or 16 bit machine), and I am trying to display number on screen (reverse of number according to code but that's a start).
Number is predefined in section .data -> num.
I am quite a newbie at assembly programming and due to the lack of material on x64 assembly (really, cant find much, and all I was able to find was quite confusing) I am unable to resolve the issue.
The issue is that the code compiles an links with no errors/warnings, but it just displays some spaces (not even newline). If I remove the call _newl code from _disprem, those spaces are also gone. There is not even segment fault or something.
By the way, algorithm to get the remainder (to get the digits in a number) is num - (num / 10) * 10
section .data
num: dq 102 ;my default number to get the reverse of (for now)
nl: db 0x0a
nlsize: equ $-nl
ten: dq 10
section .bss
rem: resq 1
remsize: equ $-rem
section .text
global _start
_start:
cmp qword [num], 0
jng _exit ;jump to _exit if num is not greater than 0
mov rax, [num] ;move the number to rax
mov rbx, [num] ;move the number to rbx as well so that i have original number in register to subtract and get the remainder
mov rcx, [ten] ;move 10 to rcx to be the divisor
div rcx ;divide number in rax by 10
mov [num], rax ;get the quotient to get the remaining number for quotient
mul rcx ;multiply number in rax by 10
sub rbx, rax ;subtract rbx - rax and store the value in rax (right?)
mov [rem], rbx ;get the remainder from rax. this must be done right after div (WHY??????????)
call _disprem ;call _disprem to display the remainder... call returns the flow back to the caller right?
jmp _start ;get to the loop again
_exit:
mov rax, 60
mov rdi, 0
syscall
_newl:
mov rax, 1
mov rdi, 1
mov rsi, nl
mov rdx, nlsize
syscall
ret
_disprem:
mov rax, 1
mov rdi, 1
add qword [rem], 0x0000000000000030 ;since the rem variable is quadword (64 bit)
mov rsi, rem
mov rdx, remsize
syscall
sub qword [rem], 0x0000000000000030 ;get me my original number back plz thanks
call _newl
ret

Why can't I sys_write from a pointer to stack memory, using int 0x80? [duplicate]

This question already has an answer here:
What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
(1 answer)
Closed 4 years ago.
; NASM
push 30 ; '0'
mov rax, 4 ; write
mov rbx, 1 ; stdout
mov rcx, rsp ; ptr to character on stack
mov rdx, 1 ; length of string = 1
int 80h
The code above does not print anything to stdout. It works when i give it a ptr to a character in section .data. What am i doing wrong?
amd64 uses a different method for system calls than int 0x80, although that might still work with 32-bit libraries installed, etc. Whereas on x86 one would do:
mov eax, SYSCALL_NUMBER
mov ebx, param1
mov ecx, param2
mov edx, param3
int 0x80
on amd64 one would instead do this:
mov rax, SYSCALL_NUMBER_64 ; different from the x86 equivalent, usually
mov rdi, param1
mov rsi, param2
mov rdx, param3
syscall
For what you want to do, consider the following example:
bits 64
global _start
section .text
_start:
push 0x0a424242
mov rdx, 04h
lea rsi, [rsp]
call write
call exit
exit:
mov rax, 60 ; exit()
xor rdi, rdi ; errno
syscall
write:
mov rax, 1 ; write()
mov rdi, 1 ; stdout
syscall
ret
30 decimal is the code of the ASCII "record separator". Whatever that is, it's probably not a printable character.
30 hexadecimal (30h or 0x30 in NASM parlance), on the other hand, is the code of the ASCII "0".
Also, you need to use the 64-bit ABI.

Resources