Author Topic: getting array values and displaying  (Read 10353 times)

Offline tim

  • Jr. Member
  • *
  • Posts: 3
getting array values and displaying
« on: November 10, 2017, 07:27:40 PM »
Hi everyone, first of all thanks for the chance to join this community.

Well, I'm trying to generate an array with the values that the user inserts himself.

Each number has two digits, that is, I capture them individually and convert them to decimal by multiplying the decimal with 10 and adding with the unit.

But there's my problem. I can convert, but I can not save to the array to be able to display later

My code:

Code: [Select]
section .data

array_tamanho EQU 1 ;Variavel fixa do tamanho do vetor (especificado no trabalho)

digite_valor            db    "Digite um valor [0-99]: "  ;Mensagem que sera mostrada para inserir os numeros de dois digitos
tamanho_digite_valor    equ   $ - digite_valor ;Tamanho da mensagem

virgula db "," ;Virgula para separar numeros na exibicao
tamanho_virgula         equ   $ - virgula ;Tamanho da mensagem

quebra_linha db 10

;array times array_tamanho DB 0 ;Inicializa a array com o valor especificado na variavel

section .bss

digito_um     resb 1 ;Variavel temporaria para digito 1, 1 bytes para ela
digito_dois   resb 1 ;Variavel temporaria para digito 2, 1 bytes para ela
enter_temp    resb 1 ;Variavel temporaria para ENTER, 1 bytes para ela
vetor         resb 200 ;Vetor onde ficara os numeros digitados
vetor_tamanho resb 1 ;Contador do vetor para fazer loops
temporario    resb 1 ;Variavel temporaria para trabalhos
numero       resb 1 ;Numero, para guardar de forma temporaria na conversao

section .text

global _start

_start:
%define SYSAPI_READ   3 ;Numero da funcao de "READ()" do Linux
%define SYSAPI_CLOSE  1 ;Numero da funcao de "CLOSE()" do Linux
%define SYSAPI_PRINT  4 ;Numero da funcao de "PRINT()" do Linux
%define STDIN         0 ;Descritor do numero para "stantard input"
%define STDO          1 ;Descritor do numero para "stantard output"

;--------------------------------------------------------------------------------------------------------

mov SI, 0 ;SI = 0, nosso contador para o "array_tamanho"

; Imprime repetidamente a mensagem para digitar valor, codigo padrao de printf
lendo:
mov eax, SYSAPI_PRINT ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO ;ebx = descritor do arquivo
mov ecx, digite_valor ;ecx = mensagem para digitar
mov edx, tamanho_digite_valor ;edx = tamanho da mensagem
int 0x80 ;retorna chamando a API do Linux

; Faz a leitura do valor digitado (primeiro digito)
mov eax, SYSAPI_READ ;eax = numero da funcao de leitura do Linux
mov ebx, STDIN ;ebx = descritor do arquivo
mov ecx, digito_um ;ecx = endereco do destino do buffer
mov edx, 1 ;edx = numeros de bytes para ler
int 0x80 ;retorna chamando a API do Linux

; Faz a leitura do valor digitado (segundo digito)
mov eax, SYSAPI_READ ;eax = numero da funcao de leitura do Linux
mov ebx, STDIN ;ebx = descritor do arquivo
mov ecx, digito_dois ;ecx = endereco do destino do buffer
mov edx, 1 ;edx = numeros de bytes para ler
int 0x80 ;retorna chamando a API do Linux

; Faz a leitura do valor digitado (ENTER para ir pro proximo)
mov eax, SYSAPI_READ ;eax = numero da funcao de leitura do Linux
mov ebx, STDIN ;ebx = descritor do arquivo
mov ecx, enter_temp ;ecx = endereco do destino do buffer
mov edx, 1 ;edx = numeros de bytes para ler
int 0x80 ;retorna chamando a API do Linux

; Trata os digitos, e os une em um registrador
sub byte[digito_um], 30h ;digito_um = digito_um - 30h, para trazer o digito para decimal
sub byte[digito_dois], 30h ;digito_dois = digito_dois - 30h, para trazer o digito para decimal

mov al, byte[digito_um] ;al = primeiro digito pegado atraves do "standart input"
mov dl, 10 ;dl = 10
mul dl ;al = ax = 10 * primeiro digito (multiplica a dezena para podermos ter um numero so)
add al, byte[digito_dois] ;al = al + digito_dois = digito_um * 10 + digito_dois (agora temos em um registrador o numero inteiro)



;mov al, byte[esi]




  inc si ;si = SI + 1
  cmp si, array_tamanho ;si == array_tamanho?
jne lendo ;SE si !== array_tamanho vai para "lendo" e repete o laco
jmp exibe_array

;--------------------------------------------------------------------------------------------------------

; Trata os numeros da array e os exibe
exibe_array:
mov ebx, vetor ;ebx = vetor
  mov al, byte[vetor_tamanho] ;al = vetor_tamanho
  mov byte[temporario], al ;

mov SI, 0 ;SI = 0, nosso contador para o "array_tamanho"

;Loop de print dos numeros da array
loop_print:
push rbx ;

  mov al, byte[vetor] ;al = byte[vetor]
  mov byte[numero], al ;byte[numero] = al

;Divisao do da dezena, para voltar ao digito unico
  movzx ax, byte[numero] ;ax = numero inteiro (juncao dos dois digitos) da array
  mov bl, 10 ;bl = 10
  div bl ;al = ax  = numero/10 (divide a dezena para termos um digito so)
  mov byte[digito_um], al ;byte[digito_um] = al
  mov byte[digito_dois], ah ;byte[digito_dois] = ah

;Adiciona 48 para se adaptar ao codigo ASCII
  add byte[digito_um], 48 ;byte[digito_um] = byte[digito_um] + 48
  add byte[digito_dois], 48 ;byte[digito_dois] = byte[digito_dois] + 48

;Exibe digito 1 (dezena)
  mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, digito_um   ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80

;Exibe digito 2 (unidade)
  mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, digito_dois   ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80

; Verifica se estamos no ultimo item do vetor, para ignorar a array
CMP SI, array_tamanho-1   ;SI == array_tamanho-1 ?
JE pula_virgula   ;SE SI == array_tamanho-1 vai para "pula_virgula"

;Exibe virgula para separar numeros
mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, virgula   ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80

pula_virgula:
  pop rbx   ;

  INC SI ;SI = SI + 1
  CMP SI, array_tamanho ;SI == array_tamanho?
JNE loop_print ;SE SI !== array_tamanho vai para "lendo" e repete o laco

mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, quebra_linha    ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80
fim:
mov eax, SYSAPI_CLOSE ;eax = numero da funcao de encerramento do Linux
xor ebx, ebx
    int 0x80 ;encerra o programa, retornando a API global do Linux (se nao encerrar, retorna "CORE DUMPED")

The result of the conversion is in the AL register, according to this piece of code

Code: [Select]
add al, byte[digito_dois] ;al = al + digito_dois = digito_um * 10 + digito_dois (agora temos em um registrador o numero inteiro)
I was trying to save the value in the array that way, but without success (I was getting core dumped):  mov byte[ebx], al

I was using NASM 64bits with UBUNTU
« Last Edit: November 10, 2017, 07:33:53 PM by tim »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: getting array values and displaying
« Reply #1 on: November 11, 2017, 01:42:16 AM »
Hi tim,

Welcome to the forum. Thanks for joining us.

I've only taken a quick look at your code. I may not understand what you intend to do. It seems that you are adding the two digits into al... and then don't do anything with al!
Code: [Select]
section .data

array_tamanho EQU 1 ;Variavel fixa do tamanho do vetor (especificado no trabalho)

digite_valor            db    "Digite um valor [0-99]: "  ;Mensagem que sera mostrada para inserir os numeros de dois digitos
tamanho_digite_valor    equ   $ - digite_valor ;Tamanho da mensagem

virgula db "," ;Virgula para separar numeros na exibicao
tamanho_virgula         equ   $ - virgula ;Tamanho da mensagem

quebra_linha db 10

;array times array_tamanho DB 0 ;Inicializa a array com o valor especificado na variavel

section .bss

digito_um     resb 1 ;Variavel temporaria para digito 1, 1 bytes para ela
digito_dois   resb 1 ;Variavel temporaria para digito 2, 1 bytes para ela
enter_temp    resb 1 ;Variavel temporaria para ENTER, 1 bytes para ela
vetor         resb 200 ;Vetor onde ficara os numeros digitados
vetor_tamanho resb 1 ;Contador do vetor para fazer loops
temporario    resb 1 ;Variavel temporaria para trabalhos
numero       resb 1 ;Numero, para guardar de forma temporaria na conversao

section .text

global _start

_start:
%define SYSAPI_READ   3 ;Numero da funcao de "READ()" do Linux
%define SYSAPI_CLOSE  1 ;Numero da funcao de "CLOSE()" do Linux
%define SYSAPI_PRINT  4 ;Numero da funcao de "PRINT()" do Linux
%define STDIN         0 ;Descritor do numero para "stantard input"
%define STDO          1 ;Descritor do numero para "stantard output"

;--------------------------------------------------------------------------------------------------------

mov SI, 0 ;SI = 0, nosso contador para o "array_tamanho"

; Imprime repetidamente a mensagem para digitar valor, codigo padrao de printf
lendo:
mov eax, SYSAPI_PRINT ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO ;ebx = descritor do arquivo
mov ecx, digite_valor ;ecx = mensagem para digitar
mov edx, tamanho_digite_valor ;edx = tamanho da mensagem
int 0x80 ;retorna chamando a API do Linux

; Faz a leitura do valor digitado (primeiro digito)
mov eax, SYSAPI_READ ;eax = numero da funcao de leitura do Linux
mov ebx, STDIN ;ebx = descritor do arquivo
mov ecx, digito_um ;ecx = endereco do destino do buffer
mov edx, 1 ;edx = numeros de bytes para ler
int 0x80 ;retorna chamando a API do Linux

; Faz a leitura do valor digitado (segundo digito)
mov eax, SYSAPI_READ ;eax = numero da funcao de leitura do Linux
mov ebx, STDIN ;ebx = descritor do arquivo
mov ecx, digito_dois ;ecx = endereco do destino do buffer
mov edx, 1 ;edx = numeros de bytes para ler
int 0x80 ;retorna chamando a API do Linux

; Faz a leitura do valor digitado (ENTER para ir pro proximo)
mov eax, SYSAPI_READ ;eax = numero da funcao de leitura do Linux
mov ebx, STDIN ;ebx = descritor do arquivo
mov ecx, enter_temp ;ecx = endereco do destino do buffer
mov edx, 1 ;edx = numeros de bytes para ler
int 0x80 ;retorna chamando a API do Linux

; Trata os digitos, e os une em um registrador
sub byte[digito_um], 30h ;digito_um = digito_um - 30h, para trazer o digito para decimal
sub byte[digito_dois], 30h ;digito_dois = digito_dois - 30h, para trazer o digito para decimal

mov al, byte[digito_um] ;al = primeiro digito pegado atraves do "standart input"
mov dl, 10 ;dl = 10
mul dl ;al = ax = 10 * primeiro digito (multiplica a dezena para podermos ter um numero so)
add al, byte[digito_dois] ;al = al + digito_dois = digito_um * 10 + digito_dois (agora temos em um registrador o numero inteiro)



;mov al, byte[esi]
mov [vetor]. al ; <----------- here!



  inc si ;si = SI + 1
  cmp si, array_tamanho ;si == array_tamanho?
jne lendo ;SE si !== array_tamanho vai para "lendo" e repete o laco
jmp exibe_array

;--------------------------------------------------------------------------------------------------------

; Trata os numeros da array e os exibe
exibe_array:
mov ebx, vetor ;ebx = vetor
  mov al, byte[vetor_tamanho] ;al = vetor_tamanho
  mov byte[temporario], al ;

mov SI, 0 ;SI = 0, nosso contador para o "array_tamanho"

;Loop de print dos numeros da array
loop_print:
push rbx ;

  mov al, byte[vetor] ;al = byte[vetor]
  mov byte[numero], al ;byte[numero] = al

;Divisao do da dezena, para voltar ao digito unico
  movzx ax, byte[numero] ;ax = numero inteiro (juncao dos dois digitos) da array
  mov bl, 10 ;bl = 10
  div bl ;al = ax  = numero/10 (divide a dezena para termos um digito so)
  mov byte[digito_um], al ;byte[digito_um] = al
  mov byte[digito_dois], ah ;byte[digito_dois] = ah

;Adiciona 48 para se adaptar ao codigo ASCII
  add byte[digito_um], 48 ;byte[digito_um] = byte[digito_um] + 48
  add byte[digito_dois], 48 ;byte[digito_dois] = byte[digito_dois] + 48

;Exibe digito 1 (dezena)
  mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, digito_um   ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80

;Exibe digito 2 (unidade)
  mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, digito_dois   ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80

; Verifica se estamos no ultimo item do vetor, para ignorar a array
CMP SI, array_tamanho-1   ;SI == array_tamanho-1 ?
JE pula_virgula   ;SE SI == array_tamanho-1 vai para "pula_virgula"

;Exibe virgula para separar numeros
mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, virgula   ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80

pula_virgula:
  pop rbx   ;

  INC SI ;SI = SI + 1
  CMP SI, array_tamanho ;SI == array_tamanho?
JNE loop_print ;SE SI !== array_tamanho vai para "lendo" e repete o laco

mov eax, SYSAPI_PRINT   ;eax = numero da funcao de exibicao do Linux
mov ebx, STDO   ;ebx = descritor do arquivo
mov ecx, quebra_linha    ;ecx = mensagem para printar
mov edx, 1   ;edx = tamanho da mensagem
int 0x80
fim:
mov eax, SYSAPI_CLOSE ;eax = numero da funcao de encerramento do Linux
xor ebx, ebx
    int 0x80 ;encerra o programa, retornando a API global do Linux (se nao encerrar, retorna "CORE DUMPED")

simply doing "mov [vetor], al" seems to help.

However... I'm running a 32-bit system and have assembled your code as 32-bit. I wasn't getting a core dump - it simply displayed "00". This may not help with the 64-bit product.

Using 32-bit system calls in 64-bit code often works... but there are reasons why it sometimes doesn't. I would suggest using 64-bit code or 32-bit code throughout. Not running a 64-bit machine, I can't help you much with that.

See if you get any good answers over on Stack Overflow. If not, come back here and we'll discuss it more.

Best,
Frank


Offline tim

  • Jr. Member
  • *
  • Posts: 3
Re: getting array values and displaying
« Reply #2 on: November 11, 2017, 01:55:40 AM »
Hi!
Quote
I've only taken a quick look at your code. I may not understand what you intend to do. It seems that you are adding the two digits into al... and then don't do anything with al!

It's exactly there that I could not continue my code, so I left it blank. I will explain what i want to do in C (because I'm kind of bad at explaining things in another language)

Code: [Select]
int array[10];

for(i = 0; i <= 10; i++) {
    scanf("%d", array[i]);
}

for(i = 0; i <= 10; i++) {
    printf("%d", array[i]);
}

I want then:

PART 1:
* Pick up 10 two-digit values (ok)
* convert these two digits into a number only (ok)
* insert this number into the array (fail)

PART 2:
* scroll through the 10 array values (fail)
* convert the values into two separate digits (ok)
* display on the screen (ok?)


I did not understand much about the system calls. Am I using it incorrectly? Here it does not return any errors, it just does not do what it is to do ..

I'm expecting a response in StackOverflow, but I'm still standing here


Offline tim

  • Jr. Member
  • *
  • Posts: 3
Re: getting array values and displaying
« Reply #3 on: November 11, 2017, 02:34:15 AM »
When i add

Code: [Select]
mov [vetor], al
and change

Quote
array_tamanho EQU 1
to
Code: [Select]
array_tamanho EQU 10
and enter the input {12,12,34,35,64,64,23,54,87,12}
the output is {12,12,12,12,12,12,12,12,12,12} but the expected is {12,12,34,35,64,64,23,54,87,12}

I imagine that I should add an INDEX to organize my array


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: getting array values and displaying
« Reply #4 on: November 11, 2017, 03:13:29 AM »
Right!
Code: [Select]
...
mov [vetor + rsi], al
inc rsi
cmp rsi, array_tamanho
jne top

; and later...
xor rsi, rsi
top2:
mov al, [vetor + rsi]
; display it
inc rsi
cmp rsi, array_tamanho
jne top2
or something like that...

I'm bad at other languages too, so I'm trying to address just the part you're having trouble with.

Best,
Frank