Wrong result after multiple read - linux

I was wondering i someone could help me with my code, i want to read more than one time from the stdin in x86 but when i read the second time, it is ignoring the number and just add the 50. I want it to work so that i can call it as many times as i need to go adding the register EAX by an arbitrary number (which i will load from variables A,B,etc later on)
section .text
global _start
_start:
call leer
call atoi
add eax,10
call itoa
call imprimir
call limpiar
call leer
call atoi
add eax,50
call itoa
call imprimir
jmp salir
;-----------ATOI
atoi:
mov esi,Buffer ;move buffer address
mov eax,0 ;where im going to keep result
mov ebx,0 ;where i put char
.atoi_start:
mov bl, byte[esi] ;get the char
je .end_atoi
cmp bl, '0' ;check if null
jb .end_atoi
cmp bl,'9'
ja .end_atoi
imul eax,10 ;multiplico resultado por 10
sub bl,0x30 ;ascii->int
add eax,ebx ;agegue el nuevo digito
inc esi ;getting ready for next char
jmp .atoi_start
.end_atoi:
ret ;at this point i have int representation in eax
;-----------ITOA
itoa:
mov ebx, eax ;mueve el numero en eax a ebx
mov esi, Buffer
mov ebx,10
add esi,10
.itoa2:
xor edx,edx
div ebx
add dl,'0' ;lo convierte en char
mov [esi],dl
dec esi
test eax,eax
jnz .itoa2
jz .doneItoa
.doneItoa:
ret
;----------------------LIMPIAR
limpiar:
;limpia buffer usando eax
xor eax,eax;
xor edx,edx
xor ecx,ecx
mov ecx, 1100 ;tamano de veces que voy a limpiar
lea edx, [Buffer] ;direccion inicial del buffer
.loop:
mov [edx+ecx],eax ;voy a limpiar de atras para adelante
dec ecx ;decremento contador y verifico si es 0 para seguir limiando
jnz .loop
ret
imprimir:
mov eax,4
mov ebx,1
mov ecx,Buffer
mov edx,1100 ;tamano
int 0x80 ;syscall
;ahora imprimo nueva linea
mov eax,4
mov ebx,1
mov ecx,nuevaLinea
mov edx,1
int 0x80
ret
leer:
;vamos a poner el msg en pantalla
mov eax,4 ;sys_write
mov ebx,1 ;stdout
mov ecx,msg ;paso el mensaje
mov edx,lenMsg ;paso el largo del mensaje
int 80h
;ahora leemos
mov eax,3 ;sys_read
mov ebx,2 ;stdin
mov ecx,Buffer
mov edx,1100
int 80h
ret
salir:
mov rax,60 ;sys_exit
mov rdi,0 ;codigo de salida
syscall
section .data
msg db 'Ingrese un numero: '
lenMsg equ $-msg
nuevaLinea db 10;nueva linea
A dq 0
section .bss
Buffer: resb 1100
B: resb 1100

In atoi, the fifth instruction
je .end_atoi
tests the Z flag which has not been set in this function. So it is jumping based on the value of Z from whatever happened before atoi is called, which is the read system call in leer.
Either put
test bl, bl
before that je instruction or just remove the je, since the end of string will be caught by the cmp '0' that follows.
But that's not a complete fix: The read system call doesn't null terminate the input. Leer should use the number of bytes read (returned by the read system call) to place a null byte in the buffer after the input.

Related

Concatenate two string in asm x86-64 intel syntax

I have tried to concatenate two strings but I keep getting segmentation faults, somebody could help me on what might be wrong with my code? Thanks!
To test it i just create to strings with dynamically allocated memory, this is a class exercise so I must free memory from the 2 parameters my fucntion gets
my code:
;int32_t strCmp(char* a, char* b)
strConcat:
push rbp ;stack frame
mov rbp, rsp
push r12 ; stringA
push r13 ; stringB
push r14 ; puntero inicio ; stringA
push r15 ; puntero inicio ; stringB
mov r12, rdi
mov r13, rsi
mov r14, r12
mov r15, r13
xor rcx, rcx ;clean rcx to do len(stringA)+leng(stringB)+1
call strLen ; len stringA
add rcx, rax
mov rdi, r13
call strLen ; len stringB
add rcx, rax
mov rdi, rcx
inc rdi
call malloc
; now rax has a pointer to new concatenated string space
.cicloA: ;loop to iterate over 1st string
cmp byte [r12], 0
jz .cicloB
xor rdx, rdx
mov dl, byte [r12]
mov byte [rax], dl
inc r12
inc rax
jmp .cicloA
.cicloB: ;loop to iterate over 2th string
cmp byte [r13], 0
jz .fin
xor rdx, rdx
mov dl, byte [r13]
mov byte [rax], dl
inc r13
inc rax
jmp .cicloB
.fin:
;add /0
mov byte [rax], 0
;release memory
mov rdi, r14
call free
mov rdi, r15
call free
pop r15
pop r14
pop r13
pop r12
pop rbp
ret
And my strLen function is
;uint32_t strLen(char* a)
strLen:
push rbp ;armo el stack frame
mov rbp, rsp
xor rax,rax
.avanzar: ;loop para ver si llegue al fin de un string
cmp byte [rdi], 0
je .fin
inc rdi
inc rax
jmp .avanzar
.fin:
pop rbp
ret
Valgrind Error:
==18885== Invalid read of size 1
==18885== at 0x400E4A: ??? (lib.asm:79)
==18885== by 0x400C49: test_strConcat (main.c:79)
==18885== by 0x400D28: main (main.c:109)
==18885== Address 0x2 is not stack'd, malloc'd or (recently) free'd
In the end, I reworte the fuction strConcat from scratch and now it works.
strConcat:
push rbp ;armo el stack frame
mov rbp, rsp
push rbx
push r12 ; stringA
push r13 ; stringB
sub rsp, 0X08
mov r12, rdi
mov r13, rsi
call strLen ;loongitud del primer string
mov ebx, eax
mov rdi, r13
call strLen ;longitud del segundo string;
add ebx, eax
mov edi, ebx
add edi, 1
call malloc
; ahora rax tiene el puntero a nuevo string para concatenar
;limpio contadores
xor r8, r8
xor r9, r9
.cicloA: ;loop para colocar stringA en nuevo string
cmp byte [r12 + r8], 0
jz .cicloB
mov dl, byte [r12 + r8]
mov byte [rax + r8], dl
inc r8
jmp .cicloA
.cicloB: ;loop para colocar stringB en nuevo string
cmp byte [r13 + r9], 0
jz .borrar
mov dl, byte [r13 + r9]
mov byte [rax + r8], dl
inc r8
inc r9
jmp .cicloB
.borrar:
;agrego el cero al final
mov byte [rax + r8], 0
mov rbx, rax
;reviso si son el mismo puntero
cmp r12, r13
je .igualitos
;libero memoria
mov rdi, r12
call free
mov rdi, r13
call free
jmp .final
.igualitos:
mov rdi, r12
call free
.final:
add rsp, 0x08
mov rax, rbx
pop r13
pop r12
pop rbx
pop rbp
ret

Nasm increment register over 9 can't display

this is my code wrote in NASM
This code is find string s2 in string s1, return index if found or return -1 if not found.
My trouble is my EBX (index), it increase 1,2,3,..9 ok but when inc to 10, they will show ':' or 11 it show ';'
I don't know why? Please help
Many thanks
Sorry for my bad English
; DINH VAN KIET
; TUAN 3
; Find String 32bit
; Build
; nasm -f elf find_string_32bit.asm -o find_string_32bit.o ; file object will be created
; ld -m elf_i386 -o find_string_32bit find_string_32bit.o ; link the object file and create executable file
; MO TA
; Tim chuoi s2 trong chuoi s1
SYS_EXIT EQU 1
SYS_READ EQU 3
SYS_WRITE EQU 4
STDIN EQU 0
STDOUT EQU 1
%define LEN 64 ; do dai toi da
%define LEN_STT 2
segment .data
msgS1 db 'Nhap chuoi s1: '
msgS1Len equ $ - msgS1
msgS2 db 'Nhap chuoi s2 (can tim): '
msgS2Len equ $ - msgS2
pos dw 00
segment .bss
s1 resw LEN
s2 resw LEN
temp resb 1
segment .learn
global _start
_start:
mov edx,msgS1Len
mov ecx,msgS1
call display
mov edx,LEN
mov ecx,s1
call read
mov edx,msgS2Len
mov ecx,msgS2
call display
mov edx,LEN
mov ecx,s2
call read
; dung eax de xu ly chuoi s2
mov eax,[s2]
mov edx,0 ; dung edx lam index
; dung ecx de xu ly chuoi s1
mov ecx,s1
mov ebx,-1 ; dung ebx de dem
lap1:
; kiem tra het chuoi
cmp byte[ecx],0
je done
; duyet tung ki tu cua s2
mov eax,[s2+edx]
mov [temp],eax
; de test
;push ebx
;push edx
;push ecx
;mov edx,1
;mov ecx,temp
;call display
;pop ecx
;pop edx
;pop ebx
; dua cac ki tu vao thanh ghi al va ah de so sanh
mov al,byte[ecx]
mov ah,[temp]
cmp ah,0xA ; kiem tra xem da het chuoi s2 hay chua?
je done
inc ebx ; tang bien vi tri
inc ecx ; tang index cua ecx
cmp al,ah ; kiem tra xem ki tu co khop nhau hay ko?
je meet
jne miss
jmp lap1
; Neu khop
meet:
cmp edx,0
jne met
push ebx
inc edx ; tang bien edx de kiem tra tiep s2
jmp lap1
; Neu tiep tuc khop
met:
inc edx
jmp lap1
; Neu khong khop
miss:
mov edx,0 ; dua edx ve dau s2 de kiem tra lai
jmp lap1
; Neu tim thay
found:
; in ra vi tri tim thay
pop ebx
add ebx,'0'
jmp exit
; Neu khong tim thay
notfound:
; in ra -1
mov ebx,'-1'
jmp exit
done:
cmp edx,0
je notfound
jne found
exit:
mov [pos],ebx
mov edx,2
mov ecx,pos
call display
mov eax,SYS_EXIT
int 80h
display:
mov eax,SYS_WRITE
mov ebx,STDOUT
int 80h
ret
read:
mov eax,SYS_READ
mov ebx,STDIN
int 80h
ret
The problem is you are displaying a number as a character.
add ebx, '0'
is a good way to convert a digit to a character for display. It is a bad way to convert a number to a character for display.
You want the following:
; variable in ebx
itoa:
mov eax, ebx
mov ecx, 10
mov esi, buf + 10
xor edx, edx
.nxt
div ecx
add dl, '0'
dec esi
mov [esi], dl
or eax, eax
jnz .nxt
mov edx, buf + 10
sub edx, esi
ret
; pointer in esi, length in edx
;... (bss area)
buf resb 10

String Reverse in Assembly language x86

I'm new to assembly language and I have this code that is suppose to reverse the string length, now I know I'm close but the program keeps crashing on me for whatever reason that is. The problem is in the STRREV PROC. What am I doing wrong in this code?
INCLUDE Irvine32.inc
.data
prompt BYTE "Enter String: ", 0
response BYTE 50 DUP(0)
message BYTE " Message entered. ",0
.code
swap MACRO a,b
xor a,b
xor b,a
xor a,b
endM
STRQRY PROC
push ebp
mov ebp, esp
push edx
push ecx
mov edx, [ebp+8]
call writestring
mov ecx, SIZEOF response
mov edx, OFFSET response
call readstring
pop ecx
pop edx
pop ebp
ret 4
STRQRY ENDP
STRLEN PROC
push ebp
mov ebp, esp
push ebx
push ecx
mov edx,[ebp+16]
mov eax, 0
counter:
mov cl,[edx+eax]
cmp cl, 0
JE done
inc eax
jmp counter
done:
pop ecx
pop ebx
pop ebp
ret 4
STRLEN ENDP
STRREV proc
push ebp
mov ebp, esp
push OFFSET response
call STRLEN
mov edx, [ebp+8]
mov esi, 0
dec eax
reverseloop:
mov ah, [edx+esi]
mov al, [edx+eax]
swap ah, al
mov [edx+esi],ah
mov [edx+eax],al
inc esi
dec eax
cmp esi, eax
jb reverseloop
ja finish
finish:
pop ebp
ret 4
STRREV endp
main PROC
push OFFSET prompt
call STRQRY
call writedec
mov edx,OFFSET message
call WriteString
push eax
call STRREV
mov edx, OFFSET response
call WriteString
exit
main ENDP
END main
The main problem in your function is changing AL and AH register and then using EAX as pointer. I decided to write a new function based on your code, read it carefully and debug your code using the right emulator.
STRREV proc
;opening the function
push ebp
mov ebp, esp
push OFFSET response
call STRLEN
mov edx, [ebp+8] ;edx = offset string to reverse
mov esi, 0
dec eax
mov ebx,edx ;ebx stores the pointer to the first character
add ebx,eax` ;now ebx store the pointer to the last character before the '$'
reverseloop:
mov ah, [edx] ;ah stores the value at string[loop count]
mov al, [ebx] ;al stores the value at string[len-loop count-1]
;"swap ah,al" is logiclly unnecessary
;better solution:
mov [ebx],ah ; string[loop count] = string[len-loop count-1]
mov [edx],al ; string[len-loop count-1] = string[loop count]
inc edx ;increment of the right-most pointer
dec ebx ;decrement of the right-most pointer
cmp ebx, eax ;compares the left-most pointer to the right-most
jb reverseloop
jmp finish ;"ja", there is no need to check a condition twice
finish:
pop ebp
ret 4
STRREV endp

Program to reverse an inputted chain of characters

I need to make a program that lets the user enter a string character by character and then print it in reverse. space means end of input (space should be entered by user.)
section .bss
c : resb 1
section .text
global _start
_start :
mov ecx, 0
mov edx, 0
saisie :
push ecx
push edx
mov eax,3
mov ebx,0
mov ecx,c
mov edx,1
int 80h
mov ecx,[c] ; put the entered value in ecx
cmp ecx,32 ; compare ecx with space.
je espace ;
pop edx
inc edx
pop ecx
jmp saisie
espace :
pop edx
cmp edx,0 ; if counter is 0 we exit if not we print what's in stack.
je fin
mov eax,4
mov ebx,1
pop ecx
int 80h
dec edx
jmp espace
fin :
mov eax, 1
mov ebx, 0
int 80h
When I enter characters and space at the end, the program just exits without error like it has done its job.
Can anyone explain this behavior and how I can correct it?

Garbage in output and wrong strings printed

I'm using nasm , and I have to do this assembly program for class that is supposed to receive a password, compare with the one stored in pass, and write whatever the password is valid or not, however for some odd reason, when printing cade it yields garbage along with the string, and when to print the other two it prints cade instead along with contr and garbage, so I'm not really sure what's happening, and if someone could help me I would really appreciate it.
Here is the macro I use to print the string
%macro inout 2
mov ah,%2
mov dx,%1
int 21h
%endmacro
And here is the program
[bits 16]
%include "macros2.inc"
[segment .data]
cade: db 'Enter the password',0ah, 0dh,'$'
invalida: db 'wrong password',0ah, 0dh,'$'
valida: db 'valid password',0ah, 0dh,'$'
pass: db '12345$'
band: db 0
contr: resb 10
[segment .code]
..start
mov ax,data
mov dx,ax
inout cade,09h
mov bx,contr
mov ah,09h
mov dx,cade
int 21h
leer:
mov ah,08h
int 21h
cmp al,0dh
je checa
mov [bx],al
inc bx
mov ah,02h
mov dl, "*"
int 21h
jmp leer
checa:
lea di,[contr]
lea si, [pass]
dec si
revisa:
loadsb
inc di
cmp [di],al
jne error
inc bx
inc di
cmp si,'$'
jl revisa
mov ah,09h
mov dx,valida
int 21h
jmp fin
error:
mov ah,09h
mov dx,invalida
int 21h
fin:
mov ah,4ch
int 21h
[bits 16]
%include "macros2.inc"
[segment .data]
cade: db 'Introduzca la contrsena',0ah, 0dh,'$'
invalida: db 'ContraseƱa no Valida',0ah, 0dh,'$'
valida: db 'ContraseƱa valida',0ah, 0dh,'$'
pass: db '12345$'
band: db 0
contr: resb 10
[segment .code]
..start
mov ax,data
mov dx,ax
inout cade,09h
mov bx,contr
mov ah,09h
mov dx,cade
int 21h
leer:
mov ah,08h
int 21h
cmp al,0dh
je checa
mov [bx],al
inc bx
mov ah,02h
mov dl, "*"
int 21h
jmp leer
checa:
lea di,[contr]
lea si, [pass]
dec si
revisa:
loadsb
inc di
cmp [di],al
jne error
inc bx
inc di
cmp si,'$'
jl revisa
mov ah,09h
mov dx,valida
int 21h
jmp fin
error:
mov ah,09h
mov dx,invalida
int 21h
fin:
mov ah,4ch
int 21h}
Doesn't take long to find your first problem...
[segment .code]
..start
mov ax,data
mov dx,ax
I think you want that to be ds, not dx.
I see you reinvent gets(). How about checking that you don't overflow your buffer?
It isn't too clear what you're trying to do after that. How about some comments?

Resources