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

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

Related

Converting C code to x86-64 bit Assembly?

I am trying to create a random letter generator for my string and I've been given a C code and will have to convert it into Assembly language for my program. I'm doing this in x86-64 bit NASM assembly language. I'm supposed to be using only system calls and not C/C++ function calls.
Here's the C/C++ code that I've got to convert:
int genran(int x,int y)
{
int a = 0;
a = a + x * 1103515245 + 12345;
return (unsigned int)(a / 65536) % (y + 1);
}
I am new to Assembly and any help is appreciated, here's what I've got so far. I know its somewhat wrong but I will be working on improving it:
section .data
string db "The random string is generated below: "
len_string equ $-string
a dd 0
x dd ?
y dd ?
rem dd 0
section .bss
string_buff resb 21 ;Our string's length is 20 characters
section .txt
global main
main:
mov rax, 1
mov rdi, 1
mov rsi, string
mov rdx, len_string
syscall
mov rax, a
mov rbx, x ;we have to come up with a value of x?
mul rbx, 1103515245
add rbx, 12345
mov rax, rbx
div rax, 65536
mov rdx, y ;we have to come up with a value of y?
add rdx, 1
;mod rax, rdx
;ret
exit:
mov rax, 60
xor rdi, rdi
syscall
mov rax, rbx
div rax, 65536
Please read the instructions; this doesn't exist. div is an opcode that only takes one argument. The code should look like
mov rax, rbx
xor rdx, rdx ; Div takes rdx:rax as an implicit 128 bit argument.
mov rcx, 65536
div rcx
At this skill level I don't recommend trying to use read or write system calls. I very much instead recommend calling the C standard library until you get the hang of it. read and write have too many gotchas. You will want to write them once and include them in a mini-library any more assembly work you do.
We can skip read by taking argument off the command line as follows:
mov rbx, [rsp + 16] ; argv[1]
Unless I'm very much mistaken, the first thing on the stack is argc, and then argv[0], then argv[1], ...

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

Assembly 'Segmentation Fault' When Trying to Print Decimal Number

I am trying to create a macro that will print a decimal number for me. My idea was to divide the number by ten, convert the remainder to ASCII and push it into the stack until the the ratio is 0. I then print the digits one by one but for some reason I get a 'Segmentation fault'.
I am using Linux, nasm, and a x86_64 processor.
%macro printInt 1
mov rax, %1
mov rbx, 0
%%loop1: ;Convert all digits to ascii
inc rbx ;Count of the digits in number
mov rdx, 0
div rax
add rdx, 48 ;Convert remainder to ascii
push rdx ;Push remainder into stack
cmp rax, 0 ;Compare ratio to 0
jne %%loop1
%%loop2: ;Print the number digit by digit
dec rbx
mov rax, 1 ;Sys_Write
mov rdi, 1 ;STDOUT
pop rsi ;Pop digit
mov rdx, 1
syscall
cmp rbx, 0
jne %%loop2
%endmacro
section .data
number1 db 123
section .text
global _start
_start:
printInt number1
mov rax, 60
mov rdi, 0
syscall
Any help is appreciated, thanks in advance!
First mistake:
number1 db 123
number1 is defined as BYTE, but will be treated as QUADWORD (mov rax, %1). Change it to
number1 dq 123
Second mistake:
printInt number1
The macro gets the argument as string. So, mov rax, %1 will be solved to mov rax, number1. In NASM, RAX will get the address of number1, not the value. Change it to
printInt [number1]
Third mistake:
div rax
means: Divide RDX:RAX by RAX, store the result in RAX and the remainder in RDX. This will always result in RAX=1 and RDX=0. Use another register with the value 10.
Fourth mistake:
pop rsi
The SYSCALL/RAX=1 routine of the kernel expects a pointer in RSI, not a number. There are several ways to address the problem. I leave that to your imagination.

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

Resources