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

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

Related

How do I print out two-digit integers in ASM, ( Linux NASM x86_64 )

This is how to print out a number, but how do I print out 2 digit numbers?
section .data
num: db 9,10
section .text
global _start
_start:
mov rax,[num]
add rax,48
mov [num],al
mov rax,1
mov rdi,1
mov rsi,num
mov rdx,2
syscall
mov rax,60
mov rdi,0
syscall
This simply prints out 9, but if I make num 12 it gives me a '<'.
I believe it is printing out the ascii character for 60, which is '<'.
mov rax,[num]
Because num just holds a byte, better not read this as a qword. Use the movzx eax, byte [num] instruction. You don't need the movzx rax, byte [num] instruction because all writing to a dword register already zeroes the high dword anyway.
but how do I print out 2 digit numbers?
Next code can do just that, printing numbers from the range [10,99].
Note that there's a placeholder right in front of the newline.
section .data
num: db 12, 0, 10
section .text
global _start
_start:
movzx eax, byte [num] ; Value LT 100
xor edx, edx
mov ebx, 10
div ebx ; Quotient in EAX, Remainder in EDX
mov ah, dl
add ax, '00' ; Convert to ASCII
mov [num], ax ; Stores 'tens' followed by 'ones'
mov rax, 1
mov rdi, 1
mov rsi, num
mov rdx, 3 ; 3 instead of 2
syscall
For a general approach you could first study Displaying numbers with DOS. It explains the methodology, but of course you'll need to adapt the code to 64-bit.
Even better info is at https://stackoverflow.com/a/46301894.

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

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

Resources