Well i want to post this code here because i want to share it and here you can do with it whatever you want to :biggrin:.
You can try the program using wrong inputs or whatever and see the results, also try good inputs.
The explanation for the code: Well, it wasn't made with the idea of been optimed code, but that can change. To control the input buffer the only method that worked for me was using AllocateConsole and FreeConsole many times as necessary. This because the buffer input has a strange behavior when some wrong inputs were inserted.
The last part has a minor check for wrong inputs, but that can be different too. Enjoy, comment, critizice, or do whatever you want with this code. :icon_mrgreen:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data?
hconsoleinput dd ?
hconsoleoutput dd ?
charswritten dd ?
charsread dd ?
charsattset dd ?
.data
binarysum dd 0
programname db "THE SIMPLEST ADDER",0
welcome db "Sum of natural numbers!",0
inpbuff db 256 dup(" ")
promptnum db "Enter a natural number: ",0
bye? db "Exit program?(Y/N): ",0
inerror db "Error! just numbers allowed of 8 digits as maximum...",0
inerror2 db "Error! you must put a number here of 1 digit as minimum...",0
errorform db "Error! just decimal digits allowed no others symbols...",0
result db 9 dup(" "),0
showsum db "The sum is: ",0
cursorp proto :word,:word
paintb proto :word,:word
asc2bin proto
bin2asc proto
upper proto
.code
main proc
allagain:
invoke AllocConsole ; Creates a new console.
invoke GetStdHandle,STD_INPUT_HANDLE
mov hconsoleinput,eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hconsoleoutput,eax
invoke SetConsoleTitle,offset programname
invoke cursorp,0,0 ; Locates the cursor.
invoke paintb,0,0 ; Clears the screen.
invoke SetConsoleTextAttribute,hconsoleoutput,\ ; Set the text and background
FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\ ; colors for the console.
BACKGROUND_GREEN
invoke WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\ ; Welcome message in screen.
offset charswritten,NULL
invoke cursorp,0,2
invoke WriteConsole,hconsoleoutput,offset promptnum,sizeof promptnum,\ ; Prompt for the first number.
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
cmp charsread,11 ; More chars than allowed?:
jb not2big ; -no, so continue.
invoke cursorp,0,0 ; -yes, so:
invoke paintb,0,0 ; *clears the screen.
invoke WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\ ; *show error message.
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\ ; *Waits for the CR key.
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; Allows inputs again (256 chars).
ENABLE_LINE_INPUT
invoke FreeConsole ; Terminates current console.
jmp allagain
not2big:
cmp charsread,2 ; Less chars than allowed?:
ja not2small ; -If no input at all (just CR):
invoke cursorp,0,0 ; *set cursor location (0,0)
invoke paintb,0,0 ; *clears the screen
invoke WriteConsole,hconsoleoutput,offset inerror2,sizeof inerror2,\ ; *show error message
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT ; *Waits for CR key.
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; All keys accepted from now,
ENABLE_LINE_INPUT ; again (256 chars).
invoke FreeConsole ; Terminates current console.
jmp allagain
not2small:
mov edi,offset inpbuff ; Address the input buffer.
mov ebx,charsread
sub ebx,2 ; Discard the LF and CR.
chek:
cmp byte ptr[edi],30h ; Is a number?
jb bad
cmp byte ptr[edi],39h
ja bad
inc edi
dec ebx
jnz chek
jmp good ; Yes, it is.
bad: ; No, is not.
invoke cursorp,0,0 ; *set cursor location (0,0)
invoke paintb,0,0 ; *clears the screen
invoke WriteConsole,hconsoleoutput,offset errorform,sizeof errorform,\ ; *show error message
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT ; *Waits for CR key.
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; All keys accepted from now,
ENABLE_LINE_INPUT ; again (256 chars).
invoke FreeConsole ; Terminates current console.
jmp allagain
good:
;mov eax,charsread ; Correct number format from here.
invoke asc2bin ; Convert ascii code to binary
invoke cursorp,0,4
invoke WriteConsole,hconsoleoutput,offset promptnum,sizeof promptnum,\ ; Prompt for the second number.
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
cmp charsread,11 ; More chars than allowed?:
jb xnot2big ; -no, so continue.
invoke cursorp,0,0 ; -yes, so:
invoke paintb,0,0 ; *clears the screen.
invoke WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\ ; *show error message.
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\ ; *Waits for the CR key.
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; Allows inputs again (256 chars).
ENABLE_LINE_INPUT
invoke FreeConsole ; Terminates current console.
mov binarysum,0 ; Clears the sum.
jmp allagain
xnot2big:
cmp charsread,2 ; Less chars than allowed?:
ja xnot2small ; -If no input at all (just CR):
invoke cursorp,0,0 ; *set cursor location (0,0)
invoke paintb,0,0 ; *clears the screen
invoke WriteConsole,hconsoleoutput,offset inerror2,sizeof inerror2,\ ; *show error message
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT ; *Waits for CR key.
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; All keys accepted from now,
ENABLE_LINE_INPUT ; again (256 chars).
invoke FreeConsole ; Terminates current console.
mov binarysum,0 ; Clears the sum.
jmp allagain
xnot2small:
mov edi,offset inpbuff ; Address the input buffer.
mov ebx,charsread
sub ebx,2 ; Discard the LF and CR.
xchek:
cmp byte ptr[edi],30h ; Is a number?
jb bad
cmp byte ptr[edi],39h
ja xbad
inc edi
dec ebx
jnz xchek
jmp xgood ; Yes, it is.
xbad: ; No, is not.
invoke cursorp,0,0 ; *set cursor location (0,0)
invoke paintb,0,0 ; *clears the screen
invoke WriteConsole,hconsoleoutput,offset errorform,sizeof errorform,\ ; *show error message
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT ; *Waits for CR key.
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; All keys accepted from now,
ENABLE_LINE_INPUT ; again (256 chars).
invoke FreeConsole ; Terminates current console.
mov binarysum,0 ; Clears the sum.
jmp allagain
xgood:
;mov eax,charsread ; Number 2 correct from here.
invoke asc2bin ; Convert ascii code to binary.
invoke bin2asc ; Convert binary sum to ascii.
invoke cursorp,0,6
invoke WriteConsole,hconsoleoutput,offset showsum,sizeof showsum,\ ; Show the result of the sum.
offset charswritten,NULL
invoke WriteConsole,hconsoleoutput,offset result,sizeof result,\
offset charswritten,NULL
decide:
invoke cursorp,0,8
invoke WriteConsole,hconsoleoutput,offset bye?,sizeof bye?,\ ; Exit program?
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset inpbuff,sizeof inpbuff,\
offset charsread,NULL
invoke upper ; Convert the answer to uppercase.
cmp al,'N'
jne wasyes?
invoke FreeConsole ; No? so all again.
mov binarysum,0 ; But we clean this
mov edi,offset result ; and this.
mov ebx,9
mov al,20h
cleaning:
stosb
dec ebx
jnz cleaning
invoke FreeConsole
jmp allagain
wasyes?:
cmp al,'Y'
je byebye
jmp decide ; Wrong answer. Do it again.
byebye:
invoke FreeConsole
invoke ExitProcess,0
main endp
paintb proc colx:word,rowy:word ; Fill into green all the screen,
local cc:COORD ; (background and foreground).
mov ax,colx
mov cc.x,ax
mov ax,rowy
mov cc.y,ax
mov eax,cc
invoke FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
FOREGROUND_GREEN,30000,eax,offset charsread
ret
paintb endp
cursorp proc col:word,row:word ; Sets the cursor location.
local cc:COORD
mov ax,col
mov cc.x,ax
mov ax,row
mov cc.y,ax
mov eax,cc
invoke SetConsoleCursorPosition,hconsoleoutput,eax
ret
cursorp endp
asc2bin proc
mov esi,10 ; Sets the powers
mov ecx,1 ; of 10.
mov ebx,charsread ; Convert 'ascii code' times.
sub ebx,2 ; Discard the LF and the CR keys.
mov edi,offset inpbuff ; Address first ascii
dec ebx ; from right
add edi,ebx ; to left.
inc ebx ; Set the counter properly again.
nextasc:
mov al,[edi] ; The rightmost ascii.
and eax,000fh ; Convert to unpacked BCD.
mul ecx ; Multiply by power of 10.
add binarysum,eax ; Accumulate the binary sum here.
mov eax,ecx
mul esi ; Next power of 10.
mov ecx,eax
dec edi ; Next ascii.
dec ebx
jnz nextasc
;mov eax,binarysum
ret
asc2bin endp
bin2asc proc
mov edi,offset result ; Address for the result
add edi,8 ; from right to left.
mov eax,binarysum
mov ecx,10
@@:
cmp eax,ecx ; We finish if the dividend
jb done ; is below the divisor.
xor edx,edx
div ecx
or dl,30h ; Ascii to unpacked BCD.
mov byte ptr[edi],dl ; Less significant digit of result.
dec edi
jmp @b
done:
or eax,30h ; This is the most significant.
mov byte ptr[edi],al
ret
bin2asc endp
upper proc ; Converts the ascii to uppercase.
mov esi,offset inpbuff
mov al,[esi]
and al,11011111b
ret
upper endp
end main
felipe,
Something worth timing is the difference between this code,
cmp byte ptr[edi],30h ; Is a number?
jb bad
cmp byte ptr[edi],39h
ja bad
and code something like this.
movzx eax, BYTE PTR [edi] ; an extra line of code
cmp eax, 30h ; do the comparisons in native data size where possible
jb bad
cmp eax, 39h
ja bad
For the extra instruction, you reduce the memory access count from 2 to 1 and sometimes this will give you a speed gain as memory is a lot slower than accessing a register.
I got it. Thanks a lot Hutch. :icon14: