NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: alissonlcunha 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:
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!
-
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.
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!
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.
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!
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.
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...
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.
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!
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
-
Well I've chopped your program up pretty badly. Seems to work, as far as it goes. Lots more to do!
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
-
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:
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
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?
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
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:
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!
-
Sorry for the delay.
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...
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
-
Hey Frank!
Thanks a lot again!
I've done some changes at this point based on your tips again.
Let me show the code:
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
-
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...
...
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
-
Hello Frank,
Let me try explain my thoughts in parts:
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:
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. :'(
...
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:
(http://pbs.twimg.com/media/DAnNcqbXgAAnAqr.jpg)
Basically, I am changing those letters (P,C,E and O) to these symbols. It is just a visual improvement. ;)
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.
... 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?
-
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?