Author Topic: Segmentation Fault  (Read 9358 times)

Offline alissonlcunha

  • Jr. Member
  • *
  • Posts: 5
Segmentation Fault
« on: May 17, 2017, 07:48:14 PM »
Hey guys,

I am kind of newbie at Assembly and I need a help here. Could you please help me?

Here is the code:
Code: [Select]
section .data
SYS_EXIT_PROGRAM  equ 1
SYS_STANDARD_OUTPUT equ 1
SYS_STANDARD_INPUT equ 2
SYS_READ_FILE  equ 3
SYS_WRITE_FILE equ 4
SYSTEM_CALL equ 0x80

;textos de exibicao para entrada do programa / texts for program inputs
TextoPedeCarta: db 'Digite a carta: ',0 ;Type a card
tamanhoTextoPedeCarta: equ $ - TextoPedeCarta
TextoPedeNaipe: db 'Digite o Naipe: ',0 ;type the suit
tamanhoTextoPedeNaipe: equ $ - TextoPedeNaipe

;textos de exibicao para erros de entrada / texts for program errors
TextoErroCarta: db 'Carta digitada inválida. [Digite uma carta entre 2,3,4,5,6,7,Q,J,K e A] ',13,10,0 ; Type a card between 2,3,4,5.....
tamanhoTextoErroCarta: equ $ - TextoErroCarta
TextoErroNaipe: db 'Naipe digitado inválido. [Digite P para Paus, C para Copas, E para Espadas e O para Ouros] ',13,10,0 ; type P(Clubs),C(Hearts),E(Spades) and O(Diamonds)
tamanhoTextoErroNaipe: equ $ - TextoErroNaipe

QuebraLinha: db 13,10,0
tamanhoQuebraLinha: equ $ - QuebraLinha ;Break a line

arrayCartas db '2','3','4','5','6','7','Q','J','K','A'
arrayNaipes db 'P','C','E','O'

section .bss
cartaDigitada: resb 21 ;typedCard
tamanhoCartaDigitada equ $ - cartaDigitada
naipeDigitado: resb 21 ;typedSuit
tamanhoNaipeDigitado: equ $ - naipeDigitado

CARTA: resb 4 ;CARD
NAIPE: resb 4 ;SUIT

section .text
global _start

;Esta rotina pede uma carta e verifica se / This routine asks for a card and verify if it is valid
; o valor é válido
; Entradas: / Entries
; ECX - texto complementar da carta / card text
Pede1Carta: ;askForCard

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
mov ecx,TextoPedeCarta
mov edx,tamanhoTextoPedeCarta
int SYSTEM_CALL

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
pop edx
pop ecx     
; precisa guardar os valores para / save the values in case of wrong typing
; caso ocorra erro de digitação
push ecx
push edx
int SYSTEM_CALL

mov eax,SYS_READ_FILE
mov ebx,SYS_STANDARD_INPUT
mov ecx,cartaDigitada
mov edx,tamanhoCartaDigitada
int SYSTEM_CALL
call VerificaCarta

Pede1Naipe: ;askForSuit
push edi
push ecx
push edx


mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
mov ecx,TextoPedeNaipe
mov edx,tamanhoTextoPedeNaipe
int SYSTEM_CALL

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
pop edx
pop ecx     
; precisa guardar os valores para /save the values in case of wrong typing
; caso ocorra erro de digitação
push ecx
push edx
int SYSTEM_CALL

mov eax,SYS_READ_FILE
mov ebx,SYS_STANDARD_INPUT
mov ecx,naipeDigitado
mov edx,tamanhoNaipeDigitado
int SYSTEM_CALL


VerificaCarta: ;verify if the card is contained on arrayCartas. in case of not, it is a wrongcard
mov eax,10
mov ecx, arrayCartas
call loop

loop:
mov ebx,[cartaDigitada]
cmp [ebx],ecx
add ecx,4
jz Pede1Carta
dec eax
jnz loop

CartaIncorreta: ;wrongcard
  mov eax,SYS_WRITE_FILE
  mov ebx,SYS_STANDARD_OUTPUT
  mov ecx,TextoErroCarta
  mov edx,tamanhoTextoErroCarta
  int SYSTEM_CALL

  jmp Pede1Carta

CartaCorreta: ; rightgcard
mov eax,[cartaDigitada]
mov [CARTA],eax
ret
 
_start:
  call Pede1Carta
  call Pede1Naipe

  mov eax,SYS_EXIT_PROGRAM
  mov ebx,0
  int SYSTEM_CALL


Here is the difficult:

This is a brazilian game, named TRUCO, and it is played with playing cards.


I am getting a Segmentation Fault when I am inserting the first card.
I dont know why it is happening. It is a problem declaring my arrays?

Another question: How can I compare every element of the array with the typed var?

I really appreciate if you can help me. I tried on brazilian forums but nobody were able to help me.

Thanks a lot guys!

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Segmentation Fault
« Reply #1 on: May 18, 2017, 01:29:32 AM »
Hi alissonlcunha,

Welcome to the Forum! I can try to help you - I might not succeed. Fortunately you speak English - I speak only English. Fortunately I'm running 32-bit Linux, so I can try your program.

Code: [Select]
section .data
SYS_EXIT_PROGRAM  equ 1
SYS_STANDARD_OUTPUT equ 1
SYS_STANDARD_INPUT equ 2
Actually, stdin is 0, stderr is 2. This works anyway!
Code: [Select]
SYS_READ_FILE  equ 3
SYS_WRITE_FILE equ 4
SYSTEM_CALL equ 0x80

;textos de exibicao para entrada do programa / texts for program inputs
TextoPedeCarta: db 'Digite a carta: ',0 ;Type a card
tamanhoTextoPedeCarta: equ $ - TextoPedeCarta
TextoPedeNaipe: db 'Digite o Naipe: ',0 ;type the suit
tamanhoTextoPedeNaipe: equ $ - TextoPedeNaipe

;textos de exibicao para erros de entrada / texts for program errors
TextoErroCarta: db 'Carta digitada inválida. [Digite uma carta entre 2,3,4,5,6,7,Q,J,K e A] ',13,10,0 ; Type a card between 2,3,4,5.....
tamanhoTextoErroCarta: equ $ - TextoErroCarta
TextoErroNaipe: db 'Naipe digitado inválido. [Digite P para Paus, C para Copas, E para Espadas e O para Ouros] ',13,10,0 ; type P(Clubs),C(Hearts),E(Spades) and O(Diamonds)
tamanhoTextoErroNaipe: equ $ - TextoErroNaipe

QuebraLinha: db 13,10,0
Linux uses only 10 (linefeed) - the carriage return (13) doesn't hurt.
Code: [Select]
tamanhoQuebraLinha: equ $ - QuebraLinha ;Break a line

arrayCartas db '2','3','4','5','6','7','Q','J','K','A'
8,9,10 are missing. Q comes before J. That's probably the way it's supposed to be. Note that these are each a single byte. That's important when you get to comparing them!
Code: [Select]
arrayNaipes db 'P','C','E','O'

section .bss
cartaDigitada: resb 21 ;typedCard
tamanhoCartaDigitada equ $ - cartaDigitada
naipeDigitado: resb 21 ;typedSuit
tamanhoNaipeDigitado: equ $ - naipeDigitado

CARTA: resb 4 ;CARD
NAIPE: resb 4 ;SUIT

section .text
global _start

;Esta rotina pede uma carta e verifica se / This routine asks for a card and verify if it is valid
; o valor é válido
; Entradas: / Entries
; ECX - texto complementar da carta / card text
Pede1Carta: ;askForCard

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
mov ecx,TextoPedeCarta
mov edx,tamanhoTextoPedeCarta
int SYSTEM_CALL
I think you're okay up to here, but this next section confuses me.
Code: [Select]
mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
pop edx
pop ecx     
; precisa guardar os valores para / save the values in case of wrong typing
; caso ocorra erro de digitação
push ecx
push edx
int SYSTEM_CALL
You pop the return address into edx and pop "argc" into ecx. Ordinarily, it would be a bad mistake to pop the return address, but since you push it back on the stack it probably won't do any harm. I don't see how it's going to print anything useful though... Similar situation with suit...
Code: [Select]
mov eax,SYS_READ_FILE
mov ebx,SYS_STANDARD_INPUT
mov ecx,cartaDigitada
mov edx,tamanhoCartaDigitada
int SYSTEM_CALL
call VerificaCarta

Pede1Naipe: ;askForSuit
push edi
push ecx
push edx


mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
mov ecx,TextoPedeNaipe
mov edx,tamanhoTextoPedeNaipe
int SYSTEM_CALL

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
pop edx
pop ecx     
; precisa guardar os valores para /save the values in case of wrong typing
; caso ocorra erro de digitação
push ecx
push edx
int SYSTEM_CALL

mov eax,SYS_READ_FILE
mov ebx,SYS_STANDARD_INPUT
mov ecx,naipeDigitado
mov edx,tamanhoNaipeDigitado
int SYSTEM_CALL


VerificaCarta: ;verify if the card is contained on arrayCartas. in case of not, it is a wrongcard
mov eax,10
mov ecx, arrayCartas
call loop
"loop" is the name of an instruction. Nasm figures out that you mean the label, not the instruction... but it might confuse a human. I'd call it something else... "compare_loop" or something - not important. In any case, I don't know why you're "call"ing it.
Code: [Select]
loop:
mov ebx,[cartaDigitada]
cmp [ebx],ecx
There's your segmentation fault, right there! You move the first four(!) bytes into ebx and try to use it as an address. You almost certainly don't have valid memory at that address, so segfault!
Code: [Select]
add ecx,4
jz Pede1Carta
dec eax
jnz loop

CartaIncorreta: ;wrongcard
  mov eax,SYS_WRITE_FILE
  mov ebx,SYS_STANDARD_OUTPUT
  mov ecx,TextoErroCarta
  mov edx,tamanhoTextoErroCarta
  int SYSTEM_CALL

  jmp Pede1Carta

CartaCorreta: ; rightgcard
mov eax,[cartaDigitada]
mov [CARTA],eax
ret
 
_start:
  call Pede1Carta
  call Pede1Naipe

  mov eax,SYS_EXIT_PROGRAM
  mov ebx,0
  int SYSTEM_CALL

That was about where I was interrupted by supper. I'll try to get back to it, but in case I don't, I wanted to let you know approximately where I think the problem is.

Later,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Segmentation Fault
« Reply #2 on: May 18, 2017, 03:14:00 AM »
Well I've chopped your program up pretty badly.  Seems to work, as far as it goes. Lots more to do!

Code: [Select]
section .data
SYS_EXIT_PROGRAM  equ 1
SYS_STANDARD_OUTPUT equ 1
SYS_STANDARD_INPUT equ 0
SYS_READ_FILE  equ 3
SYS_WRITE_FILE equ 4
SYSTEM_CALL equ 0x80

;textos de exibicao para entrada do programa / texts for program inputs
TextoPedeCarta: db 'Digite a carta: ',0 ;Type a card
tamanhoTextoPedeCarta: equ $ - TextoPedeCarta
TextoPedeNaipe: db 'Digite o Naipe: ',0 ;type the suit
tamanhoTextoPedeNaipe: equ $ - TextoPedeNaipe

;textos de exibicao para erros de entrada / texts for program errors
TextoErroCarta: db 'Carta digitada inválida. [Digite uma carta entre 2,3,4,5,6,7,Q,J,K e A] ',13,10,0 ; Type a card between 2,3,4,5.....
tamanhoTextoErroCarta: equ $ - TextoErroCarta
TextoErroNaipe: db 'Naipe digitado inválido. [Digite P para Paus, C para Copas, E para Espadas e O para Ouros] ',13,10,0 ; type P(Clubs),C(Hearts),E(Spades) and O(Diamonds)
tamanhoTextoErroNaipe: equ $ - TextoErroNaipe

QuebraLinha: db 10,0
tamanhoQuebraLinha: equ $ - QuebraLinha ;Break a line

arrayCartas db '2','3','4','5','6','7','Q','J','K','A'
arrayNaipes db 'P','C','E','O'

section .bss
cartaDigitada: resb 21 ;typedCard
tamanhoCartaDigitada equ $ - cartaDigitada
naipeDigitado: resb 21 ;typedSuit
tamanhoNaipeDigitado: equ $ - naipeDigitado

CARTA: resb 4 ;CARD
NAIPE: resb 4 ;SUIT

section .text
global _start

;Esta rotina pede uma carta e verifica se / This routine asks for a card and verify if it is valid
; o valor é válido
; Entradas: / Entries
; ECX - texto complementar da carta / card text
Pede1Carta: ;askForCard

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
mov ecx,TextoPedeCarta
mov edx,tamanhoTextoPedeCarta
int SYSTEM_CALL


mov eax,SYS_READ_FILE
mov ebx,SYS_STANDARD_INPUT
mov ecx,cartaDigitada
mov edx,tamanhoCartaDigitada
int SYSTEM_CALL
call VerificaCarta
ret

Pede1Naipe: ;askForSuit

mov eax,SYS_WRITE_FILE
mov ebx,SYS_STANDARD_OUTPUT
mov ecx,TextoPedeNaipe
mov edx,tamanhoTextoPedeNaipe
int SYSTEM_CALL


mov eax,SYS_READ_FILE
mov ebx,SYS_STANDARD_INPUT
mov ecx,naipeDigitado
mov edx,tamanhoNaipeDigitado
int SYSTEM_CALL
; verify suit
ret


VerificaCarta: ;verify if the card is contained on arrayCartas. in case of not, it is a wrongcard
mov eax,10 ; length of array
mov ecx, arrayCartas

compare_loop:
mov bl,[cartaDigitada] ; one byte
cmp [ecx],bl ; compare with one byte of array
jz CartaCorreta ; it's good!
inc ecx ; next byte in array
dec eax ; loop counter
jnz compare_loop

CartaIncorreta: ;wrongcard
  mov eax,SYS_WRITE_FILE
  mov ebx,SYS_STANDARD_OUTPUT
  mov ecx,TextoErroCarta
  mov edx,tamanhoTextoErroCarta
  int SYSTEM_CALL

  jmp Pede1Carta

CartaCorreta: ; rightgcard
mov [CARTA],bl
ret
 
_start:
  call Pede1Carta
  call Pede1Naipe

  mov eax,SYS_EXIT_PROGRAM
  mov ebx,0
  int SYSTEM_CALL

I've left "verify suit" for you. Same tune, different lyrics. One issue I see... you've got some uppercase letters in both "card" and "suit". Are you going to force the user to type uppercase or will you accept lowercase too? That makes the compare loop more complicated but it can be done. I don't know how the game goes, so I don't know what's next. Will you need a "hand" of cards or is one enough? Anyway, carry on and if you run into more trouble, feel free to ask...

Best,
Frank


Offline alissonlcunha

  • Jr. Member
  • *
  • Posts: 5
Re: Segmentation Fault
« Reply #3 on: May 18, 2017, 02:22:46 PM »
Hi Frank Kotler,

Thank you a lot for your support!

Based on your tips I FINALLY could solve my problem with the segmentation fault.

I will share my entire code:
Code: [Select]
section .data
    SYS_EXIT_PROGRAM  equ 1
    SYS_STANDARD_OUTPUT equ 1
    SYS_STANDARD_INPUT equ 2
    SYS_READ_FILE  equ 3
    SYS_WRITE_FILE equ 4
    SYSTEM_CALL equ 0x80

    ;textos de exibicao para entrada do programa
    TextoPedeCarta: db 'Informe a Carta: ',0
    tamanhoTextoPedeCarta: equ $ - TextoPedeCarta
    TextoPedeNaipe: db 'Informe o Naipe: ',0
    tamanhoTextoPedeNaipe: equ $ - TextoPedeNaipe
   
    ;textos de exibicao para erros de entrada
    TextoErroCarta: db 'Carta digitada inválida. [Digite uma carta entre 2,3,4,5,6,7,Q,J,K e A]'
    tamanhoTextoErroCarta: equ $ - TextoErroCarta
    TextoErroNaipe: db 'Naipe digitado inválido. [Digite P para Paus, C para Copas, E para Espadas e O para Ouros]'
    tamanhoTextoErroNaipe: equ $ - TextoErroNaipe

    QuebraLinha: db 13,10,0
    tamanhoQuebraLinha: equ $ - QuebraLinha

    arrayCartas db '2','3','4','5','6','7','Q','q','J','j','K','k','A','a'
    tamArrayCartas: equ $ - arrayCartas
    arrayNaipes db 'P','p','C','c','E','e','O','o'
    tamArrayNaipes: equ $ - arrayNaipes

section .bss
    cartaDigitada: resb 21
    tamanhoCartaDigitada equ $ - cartaDigitada
    naipeDigitado: resb 21
    tamanhoNaipeDigitado: equ $ - naipeDigitado

    CARTA: resb 4
    tamCARTA : equ $ - CARTA
    NAIPE: resb 4
    tamNAIPE : equ $ - NAIPE

section .text
    global _start

Pede1Carta:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoPedeCarta
    mov edx,tamanhoTextoPedeCarta
    int SYSTEM_CALL

    mov eax,SYS_READ_FILE
    mov ebx,SYS_STANDARD_INPUT
    mov ecx,cartaDigitada
    mov edx,tamanhoCartaDigitada
    int SYSTEM_CALL
    jmp VerificaCarta

Pede1Naipe:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoPedeNaipe
    mov edx,tamanhoTextoPedeNaipe
    int SYSTEM_CALL

    mov eax,SYS_READ_FILE
    mov ebx,SYS_STANDARD_INPUT
    mov ecx,naipeDigitado
    mov edx,tamanhoNaipeDigitado
    int SYSTEM_CALL
    jmp VerificaNaipe
   
VerificaCarta:
    mov eax,tamArrayCartas
    mov ecx, arrayCartas
    jmp loopCartas
    loopCartas:
        mov bl,[cartaDigitada] ;mov a carta digitada para bl
        cmp bl,[ecx] ; compara bl com o valor de ecx (ecx = MEU VETOR)
        jz CartaCorreta ; se a comparacao com o ELEMENTO ATUAL for igual a zero (ou seja, se forem iguais), pulo para CartaCorreta
        add ecx,1 ;senao, adiciono mais um no ecx (anda um indice no vetor)
        dec eax ; diminuo um do eax (eax = tamArrayCartas)
        jnz loopCartas ; enquanto eax != 0 ,faça loop
        jmp CartaIncorreta ; pula para CartaIncorreta

VerificaNaipe:
    mov eax,tamArrayNaipes
    mov ecx, arrayNaipes
    jmp loopNaipes
    loopNaipes:
        mov bl,[naipeDigitado] ;mov a carta digitada para bl
        cmp bl,[ecx] ; compara bl com o valor de ecx (ecx = MEU VETOR)
        jz NaipeCorreto ; se a comparacao com o ELEMENTO ATUAL for igual a zero(ou seja, se forem iguais), pulo para NaipeCorreto
        add ecx,1 ;senao, adiciono mais um no ecx (anda um indice no vetor)
        dec eax ; diminuo um do eax (eax = tamArrayNaipes)
        jnz loopNaipes ; enquanto eax != 0 ,faça loop
        jmp NaipeIncorreto ; pula para NaipeIncorreto
       
CartaIncorreta:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoErroCarta
    mov edx,tamanhoTextoErroCarta
    int SYSTEM_CALL
    jmp Pede1Carta

CartaCorreta:
    mov ecx,[cartaDigitada]
    mov [CARTA],ecx
    ret
   
NaipeIncorreto:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoErroNaipe
    mov edx,tamanhoTextoErroNaipe
    int SYSTEM_CALL
    jmp Pede1Naipe

NaipeCorreto:
    mov ecx,[naipeDigitado]
    mov [NAIPE],ecx
    ret
   
MontaCarta:   
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,CARTA
    mov edx,tamCARTA
    int SYSTEM_CALL

    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,NAIPE
    mov edx,tamNAIPE
    int SYSTEM_CALL

    ret
   
_start:
    call Pede1Carta
    call Pede1Naipe
    call MontaCarta
    mov eax,SYS_EXIT_PROGRAM
    mov ebx,0
    int SYSTEM_CALL

Quote
One issue I see... you've got some uppercase letters in both "card" and "suit". Are you going to force the user to type uppercase or will you accept lowercase too? That makes the compare loop more complicated but it can be done.
I solved this problem by inserting the lower cases at in my array. Is there any other way to to this?

Code: [Select]
    arrayCartas db '2','3','4','5','6','7','Q','q','J','j','K','k','A','a'
    tamArrayCartas: equ $ - arrayCartas
    arrayNaipes db 'P','p','C','c','E','e','O','o'
    tamArrayNaipes: equ $ - arrayNaipes



Quote
8,9,10 are missing. Q comes before J. That's probably the way it's supposed to be. Note that these are each a single byte. That's important when you get to comparing them!
Yes, at this game this is the correct sequence for the cards. We don't use 8,9 and 10. And the correct sequence for the cards is that: 4<5<6<7<Q<J<K<A<2<3

Here is an explanation of this brazilian game:
https://www.pagat.com/put/truco_br.html
I am using the Truco Paulista version. It is a little complicated to understand at first, but what I need to do here now, is to show correct sequence of the order after the "turned card" ( This card is the typed card at my program :D). As can you see, this is dynamically changing depending on the "turned card".


I will share what my teacher proposed for this homework:
Code: [Select]
Create a program in Linux assembly that can list according to the facing card and in ascending order of
Value, all cards from the TRUCO deck, including your suit.
Valid entries are:
• the identification of a card (2,3,4,5,6,7, Queen, Jack, King, Ace);
• the respective suit (clubs, diamonds, spades, hearts).
It is recommended to request this user data by typing only one character for the card and another for the suit.
Which letters or numbers to use, is at the discretion of the team, which should make it very clear to the user what the valid entries are.
The program must validate the data entered and ask again if any information entered is not correct.
There must also be a delicate way out, duly explained to the user.
The program should allow the input of data, in both uppercase and lowercase.
The output will be at least 13 lines of text, indicating in the proper order (according to the turned card) the remaining 39 cards in the pack.
Cards of equal value and different suit must be on the same line, while higher cards should be listed on subsequent lines.
After submitting the text, the program should request another card or allow the user to decide to terminate the program.
Example: if the user indicates that the turned card is the K of diamonds, the output should be similar to the following.
4 of diamonds, 4 of spades, 4 of hearts, 4 of clubs,
5 of diamonds, 5 of spades, 5 of hearts, 5 of clubs,
6 of diamonds, 6 of spades, 6 of hearts, 6 of clubs,
7 of diamonds, 7 of spades, 7 of hearts, 7 of clubs,
Q of diamonds, Q of spades, Q of hearts, Q of clubs,
J of diamonds, J of spades, J of hearts, J of clubs,
K of spades, k of hearts, k of clubs,
2 of diamonds, 2 of spades, 2 of hearts, 2 of clubs,
3 of diamonds, 3 of spades, 3 of hearts, 3 of clubs,
Ace of diamonds,
Ace of spades,
Ace of hearts,
Ace of clubs.
It is very important to emphasize that:
• “Manilhas” can not be in the same line as they never tie;
• The list of 39 cards provided at the output can not contain the card turned;
• The order of the numbers varies according to the facing card;
• You can put alternative or complementary information in the output, as long as it does not affect the correct order of the cards;
• The program can be absurdly large if good programming practices are not used and a good planning of data structures;
• In addition to the correct order of the cards, the score must also be correct to take grade 100.

I know that it is a little complicated to understand the rules, but I will probably need your help soon again.  ;D

Thank you bro!
« Last Edit: May 18, 2017, 05:54:49 PM by alissonlcunha »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Segmentation Fault
« Reply #4 on: May 21, 2017, 04:02:17 PM »
Sorry for the delay.
Quote
I solved this problem by inserting the lower cases at in my array. Is there any other way to to this?
Yes. My first thought was that I liked your method better - simpler. On further thought, there might be a disadvantage to it. What goes into [CARTA] and [NAIPE] might  be either case. You may need to check for both in the future. It might be better to force whatever the user types to uppercase, so there  will only be one option to test...
Code: [Select]
cmp bl, "a"
jb not_lower
cmp bl, "z"
ja not_lower
and bl, 0DFh ; force to uppercase
not_lower:
; now look for it in your array(s)
That's untested, but ahould be close enough to give you the idea of a different way to do it. I also notice you're putting four bytes into those variables - you may only want one.

Best,
Frank


Offline alissonlcunha

  • Jr. Member
  • *
  • Posts: 5
Re: Segmentation Fault
« Reply #5 on: May 24, 2017, 02:54:46 AM »
Hey Frank!

Thanks a lot again!

I've done some changes at this point based on your tips again.
Let me show the code:

Code: [Select]
section .data
    SYS_EXIT_PROGRAM  equ 1
    SYS_STANDARD_OUTPUT equ 1
    SYS_STANDARD_INPUT equ 2
    SYS_READ_FILE  equ 3
    SYS_WRITE_FILE equ 4
    SYSTEM_CALL equ 0x80

    ;textos de exibicao para entrada do programa
    TextoPedeCarta: db 'Informe a Carta: ',0
    tamanhoTextoPedeCarta: equ $ - TextoPedeCarta
    TextoPedeNaipe: db 'Informe o Naipe: ',0
    tamanhoTextoPedeNaipe: equ $ - TextoPedeNaipe
   
    ;textos de exibicao para erros de entrada
    TextoErroCarta: db 'Carta digitada inválida. [Digite uma carta entre 4,5,6,7,Q,J,K,A,2 e 3]',10
    tamanhoTextoErroCarta: equ $ - TextoErroCarta
    TextoErroNaipe: db 'Naipe digitado inválido. [Digite P para Paus, C para Copas, E para Espadas e O para Ouros]',10
    tamanhoTextoErroNaipe: equ $ - TextoErroNaipe

    QuebraLinha: db 13,10,0
    tamanhoQuebraLinha: equ $ - QuebraLinha

    arrayCartas db '4','5','6','7','Q','J','K','A','2','3'
    tamArrayCartas: equ $ - arrayCartas
    arrayNaipes db 'P','C','E','O'
    tamArrayNaipes: equ $ - arrayNaipes
   
    NaipePaus: db 'P'
    NaipeCopas: db 'C'
    NaipeEspadas: db 'E'
    NaipeOuros: db 'O'
    SimbPaus: db '?',0
    SimbCopas: db '?',0
    SimbEspadas: db '?',0
    SimbOuros: db '?',0

section .bss
    cartaDigitada: resb 21
    tamanhoCartaDigitada equ $ - cartaDigitada
    naipeDigitado: resb 21
    tamanhoNaipeDigitado: equ $ - naipeDigitado

    CARTA: resb 1
    tamCARTA : equ $ - CARTA
    NAIPE: resb 4
    tamNAIPE : equ $ - NAIPE

section .text
    global _start

Pede1Carta:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoPedeCarta
    mov edx,tamanhoTextoPedeCarta
    int SYSTEM_CALL

    mov eax,SYS_READ_FILE
    mov ebx,SYS_STANDARD_INPUT
    mov ecx,cartaDigitada
    mov edx,tamanhoCartaDigitada
    int SYSTEM_CALL
    jmp VerificaCarta

Pede1Naipe:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoPedeNaipe
    mov edx,tamanhoTextoPedeNaipe
    int SYSTEM_CALL

    mov eax,SYS_READ_FILE
    mov ebx,SYS_STANDARD_INPUT
    mov ecx,naipeDigitado
    mov edx,tamanhoNaipeDigitado
    int SYSTEM_CALL
    jmp VerificaNaipe
   
VerificaCarta:
    mov eax,tamArrayCartas
    mov ecx, arrayCartas
    mov bl,[cartaDigitada] ;mov a carta digitada para bl
    cmp bl, 'a'
        jb loopCartas
    cmp bl, 'z'
        ja loopCartas
    and bl, 0DFh ; força para letras maiusculas
    mov [cartaDigitada],bl
    jmp loopCartas

loopCartas:
    cmp bl,[ecx] ; compara bl com o valor de ecx (ecx = MEU VETOR)
        jz CartaCorreta ; se a comparacao com o ELEMENTO ATUAL for igual a zero (ou seja, se forem iguais), pulo para CartaCorreta
    add ecx,1 ;senao, adiciono mais um no ecx (anda um indice no vetor)
    dec eax ; diminuo um do eax (eax = tamArrayCartas)
        jnz loopCartas ; enquanto eax != 0 ,faça loop
    jmp CartaIncorreta ; pula para CartaIncorreta

VerificaNaipe:
    mov eax,tamArrayNaipes
    mov ecx, arrayNaipes
    mov bl,[naipeDigitado] ;mov a carta digitada para bl
    cmp bl, 'a'
        jb loopNaipes
    cmp bl, 'z'
        ja loopNaipes
    and bl, 0DFh ; força para letras maiusculas
    mov [naipeDigitado],bl
    jmp loopNaipes

loopNaipes:     
        cmp bl,[ecx] ; compara bl com o valor de ecx (ecx = MEU VETOR)
            jz NaipeCorreto ; se a comparacao com o ELEMENTO ATUAL for igual a zero(ou seja, se forem iguais), pulo para NaipeCorreto
        add ecx,1 ;senao, adiciono mais um no ecx (anda um indice no vetor)
        dec eax ; diminuo um do eax (eax = tamArrayNaipes)
            jnz loopNaipes ; enquanto eax != 0 ,faça loop
        jmp NaipeIncorreto ; pula para NaipeIncorreto
       
CartaIncorreta:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoErroCarta
    mov edx,tamanhoTextoErroCarta
    int SYSTEM_CALL
    jmp Pede1Carta

CartaCorreta:
    mov ecx,[cartaDigitada]
    mov [CARTA],ecx
    ret
   
NaipeIncorreto:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,TextoErroNaipe
    mov edx,tamanhoTextoErroNaipe
    int SYSTEM_CALL
    jmp Pede1Naipe

NaipeCorreto:
    mov ecx,[naipeDigitado]
    mov [NAIPE],ecx
    jmp MudaNaipe
     
MudaNaipe:
    mov bl,[NAIPE]
    cmp bl,'P'
        jz MudaPaus
    cmp bl,'C'
        jz MudaCopas
    cmp bl,'E'
        jz MudaEspadas
    cmp bl, 'O'
        jz MudaOuros
   
MudaPaus:
    mov eax,[SimbPaus]
    mov [NAIPE],eax
    ret
MudaCopas:
    mov eax,[SimbCopas]
    mov [NAIPE],eax
    ret
MudaEspadas:
    mov eax,[SimbEspadas]
    mov [NAIPE],eax
    ret
MudaOuros:
    mov eax,[SimbOuros]
    mov [NAIPE],eax
    ret

MontaCarta:
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,CARTA
    mov edx,tamCARTA
    int SYSTEM_CALL

    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,NAIPE
    mov edx,tamNAIPE
    int SYSTEM_CALL
   
    mov eax,SYS_WRITE_FILE
    mov ebx,SYS_STANDARD_OUTPUT
    mov ecx,QuebraLinha
    mov edx,tamanhoQuebraLinha
    int SYSTEM_CALL
   
    ret
   
_start:
    call Pede1Carta
    call Pede1Naipe
    call MontaCarta
    mov eax,SYS_EXIT_PROGRAM
    mov ebx,0
    int SYSTEM_CALL


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Segmentation Fault
« Reply #6 on: May 24, 2017, 06:13:16 AM »
One of my tips was that you're putting four bytes into "CARTA" and "NAIPE". One of your latest changes is that you've reduced "CARTA" from "resb 4" to "resb 1". At this point, it is an error to put four bytes into it. It may not do any harm - the "extra" three bytes go into "NAIPE" and you overwrite them later - but it still isn't "right".

I'm getting some "funny" results when you display the card and suit. I don't think it's because of this, but I'm going to have to look at it... not right now...

Think about how big you need these variables to be... and how you use them. I just recently looked at that link that explains the game, and I'm a bit confused. I think, at this point, you need just one byte for the card and one byte for the suit.

... the way sys_read works from stdin (it's still 0 not 2 but it still doesn't matter) it doesn't return until the user hits "enter" (no matter how much garbage they type!). The linefeed (ascii 10) is part of the input, and goes in your buffer (and is counted in eax). So you want at least two bytes in your buffer - one useful character and the linefeed. However, you usually want to ignore the linefeed from then on. If the pesky user types more than what you allow in edx, the "excess" remains in the OS's input buffer (not your buffer - I think of it as the "keyboard buffer") and it will mess up future reads. You can prevent such an "overflow" by making sure you get the linefeed - reading more and throwing it away until you do. If you've got a "well behaved user" you don't have to worry about this but a "real user" - who knows what they'll do? I hope I haven't confused you by bringing this up.

Anyway, you're doing quite well. You do some processing on NAIPE that I don't understand...
Code: [Select]
...
    SimbPaus: db '?',0
    SimbCopas: db '?',0
    SimbEspadas: db '?',0
    SimbOuros: db '?',0

...
    jmp MudaNaipe
; (you don't need this jump)   
 
MudaNaipe:
    mov bl,[NAIPE]
    cmp bl,'P'
        jz MudaPaus
    cmp bl,'C'
        jz MudaCopas
    cmp bl,'E'
        jz MudaEspadas
    cmp bl, 'O'
        jz MudaOuros
   
MudaPaus:
    mov eax,[SimbPaus]
    mov [NAIPE],eax
    ret
MudaCopas:
    mov eax,[SimbCopas]
    mov [NAIPE],eax
    ret
MudaEspadas:
    mov eax,[SimbEspadas]
    mov [NAIPE],eax
    ret
MudaOuros:
    mov eax,[SimbOuros]
    mov [NAIPE],eax
    ret

You seem to have a zero-terminated variable to put the suit character into... but you're putting four bytes into it, overwriting the zero (with the linefeed?). I'm not sure what you intend to do here...

As I said, I'm going to have to look at this some more - probably not tonight...

Later,
Frank


Offline alissonlcunha

  • Jr. Member
  • *
  • Posts: 5
Re: Segmentation Fault
« Reply #7 on: May 24, 2017, 07:20:26 PM »
Hello Frank,

Let me try explain my thoughts in parts:

Quote
I'm getting some "funny" results when you display the card and suit. I don't think it's because of this, but I'm going to have to look at it... not right now...
This is happening because of this part bellow:
Code: [Select]
SimbPaus: db '?',0
SimbCopas: db '?',0
SimbEspadas: db '?',0
SimbOuros: db '?',0

I think the forum doesn't show special chars like the suits. ;D I just copy-paste my code here and I didn't see that it was suppressed. :'(

Code: [Select]
...
    SimbPaus: db '?',0 ;Clubs symbol
    SimbCopas: db '?',0 ;Hearts Symbol
    SimbEspadas: db '?',0 ;Spades Symbol
    SimbOuros: db '?',0 ; Diamonds Symbol

...
    jmp MudaNaipe
; (you don't need this jump)   ;I just got this jump to change the letters into symbols
 
MudaNaipe:
    mov bl,[NAIPE]
    cmp bl,'P'
        jz MudaPaus ; if the typed letter is P, goto MudaPaus(ChangeItToClubs)
    cmp bl,'C'
        jz MudaCopas
    cmp bl,'E'
        jz MudaEspadas
    cmp bl, 'O'
        jz MudaOuros
   
MudaPaus: ;Change the letter 'P' to the Clubs Symbol
    mov eax,[SimbPaus]
    mov [NAIPE],eax
    ret
MudaCopas:
    mov eax,[SimbCopas] ;Change the letter 'C' to the Hearts Symbol
    mov [NAIPE],eax
    ret
MudaEspadas:
    mov eax,[SimbEspadas] ;Change the letter 'E' to the Spades Symbol
    mov [NAIPE],eax
    ret
MudaOuros:
    mov eax,[SimbOuros] ;Change the letter 'O' to the Diamonds Symbol
    mov [NAIPE],eax
    ret

The final version should be like this:


Basically, I am changing those letters (P,C,E and O) to these symbols. It is just a visual improvement. ;)

Quote
One of my tips was that you're putting four bytes into "CARTA" and "NAIPE". One of your latest changes is that you've reduced "CARTA" from "resb 4" to "resb 1". At this point, it is an error to put four bytes into it. It may not do any harm - the "extra" three bytes go into "NAIPE" and you overwrite them later - but it still isn't "right".
Well, let me explain why I did it.
I've changed to resb1, but I don't know why the assembler converted the symbols at "funny" results. I got it fixed, just when I returned it to resb4. I think, that these special chars uses more than 1byte.

Quote
... the way sys_read works from stdin (it's still 0 not 2 but it still doesn't matter) it doesn't return until the user hits "enter" (no matter how much garbage they type!). The linefeed (ascii 10) is part of the input, and goes in your buffer (and is counted in eax). So you want at least two bytes in your buffer - one useful character and the linefeed. However, you usually want to ignore the linefeed from then on. If the pesky user types more than what you allow in edx, the "excess" remains in the OS's input buffer (not your buffer - I think of it as the "keyboard buffer") and it will mess up future reads. You can prevent such an "overflow" by making sure you get the linefeed - reading more and throwing it away until you do. If you've got a "well behaved user" you don't have to worry about this but a "real user" - who knows what they'll do? I hope I haven't confused you by bringing this up.
I tried to understand this part, but it is a little confusing to me. Can you explain again?


Offline alissonlcunha

  • Jr. Member
  • *
  • Posts: 5
Re: Segmentation Fault
« Reply #8 on: May 24, 2017, 07:47:32 PM »
Let me explain how this game works:

The cards has values, as I told you: 4<5<6<7<Q<J<K<A<2<3
So, 3 is the higher card and 4 is the lower card.

When a card is turned (the typed card I was working until now), the next card form the left to right became the higher card on the game.
This card is called MANILHA.

For example: The turned card is 5 (the user type this card). The new values for the cards are: 4<5<7<Q<J<K<A<2<3<6 (6 is the MANILHA)
If the turned card is a 3: 5<6<7<Q<J<K<A<2<3<4 (4 is the MANILHA)
If the turned Card is a J: 4<5<6<7<Q<J<A<2<3<4<K (K is the MANILHA)

I told you to, that the suits has a value to: Clubs > Hearts > Spades > Diamonds
This is just applicable for the MANILHA card.
So, when the A is the MANILHA card, I have this sequence: A Clubs > A Hearts > A Spades > A Diamonds
When the 2 is the MANILHA CARD: 2 Clubs > 2 Hearts > 2 Spades > 2 Diamonds



Now the next step on the program is:

I have an array that is previously sorted on this order: 4,5,6,7,Q,J,K,A,2,3
This is sorted from the lower to the higher.

When the user types a card, I have to sort this array again, considering that the card that goes after the "typed card" (MANILHA card) is the higher card now. It is a little strange, but I will give an example.

Let suppose that the user typed 3P

It corresponds to the 3 card and the Club suit. So, I have to resort my array to this values: 5,6,7,Q,J,K,A,2,3,4

After that, I have to print all the cards from the lower to the higher:

5 clubs, 5 hearts, 5 spades, 5 diamonds
6 clubs, 6 hearts, 6 spades, 6 diamonds
7 clubs, 7 hearts, 7 spades, 7 diamonds
Q clubs, Q hearts, Q spades, Q diamonds
J clubs, J hearts, J spades, J diamonds
K clubs, K hearts, K spades, K diamonds
A clubs, A hearts, A spades, A diamonds
2 clubs, 2 hearts, 2 spades, 2 diamonds
3 hearts, 3 spades, 3 diamonds (3 of Clubs is not printed because it is the "turned card')
4 diamonds
4 spades
4 hearts
4 clubs

Excepting the MANILHA cards, same cards, has the same value.
So, 5 of clubs has the same value as the 5 of diamonds. (These cards [in this case] are the lowers card at the game.
4 of clubs is the higher card now.

It is a little clear now?