News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

5+ 4 = 7 - Ok i did it wrong, but where?

Started by zer0code, June 09, 2011, 12:37:26 AM

Previous topic - Next topic

zer0code

Good night everyone.

Well, following what Hutch said to me, i just abandoned the old style asm, focused on 32-bits programming and using some things i've learned from reading ebooks, i tried to develop a single calculator that only sums 2 numbers
Everything went as expected till i see the result
5
+
4
= 7

I know i must be did something wrong, but i was not able to notice what so far
Plus, consider that i'm a complete newbie on asm, and this program must be using a lot more instructions than needed, i would like to ask if you guys could point me what i could get better

Here's the program


.386
.model flat, stdcall
option casemap: none

include \masm32\include\masm32rt.inc

.data?
buffer db 100 dup(?)

.data
input1 db 0
input2 db 0
msg_in db "Entre com um numero: ",0
msg_in_2 db "Entre com outro numero: ", 0
msg_out_1 db "Primeiro Numero - ", 0
msg_out_2 db "Segundo Numero - ", 0
msg_sum db "A soma e: ",0

.code

start:
    xor eax,eax ; cleaning up EAX

    invoke StdOut, addr msg_in     ; asking to enter a number

    invoke StdIn, addr buffer, 100 ;reading the number

    mov al, [buffer]              ;storing the read number into AL

    mov [input1], al

    invoke StdOut, addr msg_out_1 ; shows output msg

    invoke StdOut, addr input1    ; and the number that was read

    invoke StdOut, addr msg_in_2  ; asking for a second number

    mov buffer, 0                 ; cleaning up buffer

    invoke StdOut, addr buffer

    invoke StdIn, addr buffer, 100

    invoke StdOut, addr msg_out_2

    invoke StdOut, addr buffer ;

    add al, [buffer]    ; in theory, al += buffer. But al stores the first number, so it adds both numbers and stores in al

    mov [buffer], al    ; as StdOut do not let me shows any register, i have to mov the content to buffer

    invoke StdOut, addr msg_sum

    invoke StdOut, addr buffer ;and finally, shows the sum

    inkey

    ret
end start


Thanks a lot  ::)
PS: i was trying to save the state of AL by pushing it on stack but i couldn't. Can i only save 16bits registers + on the stack?

dedndave

in 32-bit code, it's best to maintain 4-alignment of the stack at all times
that means - push dwords only, or adjust ESP by values evenly divisible by 4

one problem you are having is that the numbers entered by the user are in ASCII string form
to perform math on them, you need to convert them to binary form
after your math is complete, they need to be converted back to ASCII string form to make sense for display

you could perform ASCII string math, but that is kind of sloppy, and probably not what you were going for   :P

zer0code

Thanks dave, ill convert all bytes to dwords.
I'm still looking for any procedure that could convert the values for me, and i guess i can find anything usefull by googling it

qWord

hi,
for converting strings to numbers, you can either use the crt function sscanf or the predefined macros a2sd,a2ud,... -> see /masm32/macros/macros.asm
here an cute example  :bg
include masm32rt.inc
.code
main proc
LOCAL res:REAL8
LOCAL r8:REAL8
LOCAL operator[2]:CHAR

mov DWORD ptr res+0,0 ; 0 = start value
mov DWORD ptr res+4,0 ;
mov CHAR ptr operator[1],0 ; term zero

print "press CTRL+C for exit",13,10

mov esi,input("Operand : ")
fn crt_sscanf,esi,"%lf",ADDR res
.while 1
mov esi,input("Operator: ")
fn crt_sscanf,esi,"%c",ADDR operator[0]
.while SDWORD ptr rv(InString,1,"+-*/",ADDR operator[0]) <= 0
print "invalid operator!",13,10
fn InString,0,"+-*/",ADDR operator
.endw
mov esi,input("Operand : ")
fn crt_sscanf,esi,"%lf",ADDR r8
fld res
.if operator == '+'
fadd r8
.elseif operator == '-'
fsub r8
.elseif operator == '*'
fmul r8
.else
fdiv r8
.endif
fstp res
print "result: "
print real8$(res),13,10
.endw
exit

main endp
end main
FPU in a trice: SmplMath
It's that simple!

dedndave

the sval or uval macro may be used
refer to the help files.....
masm32\help\hlhelp.chm

zer0code

dave and qWord, thanks a lot!

I noticed that i must append the string terminator to the current read number or it will fail i guess...
i mean, i used atodw to convert from string to DW, stored in EAX
in the end i used the proc dwtoa to convert back to string but something went wrong since 5+4 = 2800 and something

question: is it ok to use atodw/dwtoa? i found a proc that add's the terminator, szappend i guess...
also, since atodw does not refers to signed nor unsigned DW in help file, what does it assumes?

qWord

Quote from: zer0code on June 09, 2011, 01:55:49 AMquestion: is it ok to use atodw/dwtoa? i found a proc that add's the terminator, szappend i guess...
also, since atodw does not refers to signed nor unsigned DW in help file, what does it assumes?
atodw and dwtoa assumes unsigned values (=DWORD). If you want to use signed values use crt_sscanf or, as said, the predefined macros a2ud/a2sd. Also you can use the functions l2oa and atol.
FPU in a trice: SmplMath
It's that simple!

zer0code

i would write something here but....

updated: nvm, i just MADE IT WORK! finally, and totally revamped. I would like to ask to you guys that point me if i'm not doing it well, OR not in a good manner


.386
.model flat, stdcall
option casemap: none

include \masm32\include\masm32rt.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib


.data?
buffer dd 100 dup(?)

.code

align 4

start:
    xor eax, eax   
    mov eax, input("Type a number: ", 62, " ")
    invoke atodw, addr [eax]
    xor ebx,ebx
    mov ebx,eax
    mov eax, input("Type another number", 62, " ")
    invoke atodw, addr [eax]
    add eax, ebx
    invoke dwtoa, eax, addr buffer
    invoke StdOut, addr buffer    
    inkey
    ret
end start


at least 5+4 = 9 now...phew  :bg
I just need to figure out why passing the register values to the variables and converting was not working...working directly with registers was the best choice but sometimes i'll need vars to help me with values

ps: where're my manners, thanks dave, thanks qWord, you guys made it by directing me to the help files, i discovered a lot of usefull things there, and i hope to discover more tomorrow....

hutch--

You can do it in registers but they are a limited resource. If you create a procedure you can use LOCAL variables to store results in without having to use up the free registers you have. With your code example you can add a few extra variables to the uninitialised data section ".data? to do this.


.data?
pstr1 dd ?
pstr2 dd ?


Then write the result of each input to the variable,


mov pstr1, eax


This way you don't get caught with not enough registers or needing to preserve certain registers.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zer0code

Quote from: hutch-- on June 09, 2011, 05:39:08 AM
You can do it in registers but they are a limited resource. If you create a procedure you can use LOCAL variables to store results in without having to use up the free registers you have. With your code example you can add a few extra variables to the uninitialised data section ".data? to do this.


.data?
pstr1 dd ?
pstr2 dd ?


Then write the result of each input to the variable,


mov pstr1, eax


This way you don't get caught with not enough registers or needing to preserve certain registers.

i was doing that way before, i gave up because the results were completely messed (ok, i just have 2 days of assembly, that must be the main reason)
What happens is: when i do your way, if i type "5" and move eax value to some variable (even if it's on data? section), i just get wierd characters
like P@!P for instance...

im still trying to realize what the compiler is doing with my value...

here's the example i was talking about (another one i just wrote)

.386
.model flat, stdcall

include \masm32\include\masm32rt.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib

.data?
pstr1 dd ?

.code

start:
    mov eax, input("Type any number: ", 62, " ")
    invoke atodw, addr [eax] ;          pass the converted value to EAX
    mov pstr1, eax ;                        moves the converted value to pstr1, for instance, 5
    invoke StdOut, addr pstr1 ;         prints out wierd char, not 5. If i use print str$(eax) it will print 5, not the wierd char
    inkey
    ret
end start



hutch--

This is your problem,


invoke StdOut, addr pstr1


You are getting the ADDRESS of an ADDRESS.

Try it without the ADDR.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zer0code

Quote from: hutch-- on June 09, 2011, 06:06:59 AM
This is your problem,


invoke StdOut, addr pstr1


You are getting the ADDRESS of an ADDRESS.

Try it without the ADDR.

You were right, indeed, you designed it  :bg
And i noticed what you said by LOOKING at StdOut and Print functions, i was doing something wrong

now using variables (your tip)
.386
.model flat, stdcall

include \masm32\include\masm32rt.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib

.data?
pstr1 dd ?
pstr2 dd ?

.code

start:
    start:
    mov pstr1, input("Type any number: ", 62, " ")   
    invoke atodw, pstr1
    mov pstr1, eax
    xor eax, eax
    mov pstr2, input("Type another number: ", 62, " ")
    invoke atodw, pstr2
    add eax, pstr1
    mov pstr2, eax
    print str$(pstr2), " is the final sum", 13,10
    inkey
    ret
end start

end start


OR by removing ADDR from StdOut
Thanks hutch, you saved my ....its 3:09, my day! hehe
time to get some sleep or ill automatically reboot in 10 minutes
Tomorrow i'd like to improve this "calculator", by passing all operation logic to procedures, add unsigned dwords, and finally, packing everything in a DLL.
Maybe i can import it on C# and play with UnManaged Code

Again, thanks  :U
update b4 sleep: Just for testing purpouses, i removed the ADDR from StdOut on my previous (working) program. When it goes to display the result, crashes. Anything related to win 7 64-bits? print str$() works fine, StdOut with ADDR too (after converting everything from registers and pass the value to a variable)

Night'

hutch--

Looks like you are doing fine. Now the distinction you need to keep an eye on is what an address is. If a function returns an address you don't need to add the ADDR before it as it is already an address.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Neil

The next step is to filter users input to make sure that it is a digit 0 to 9 & not some other character :wink

dedndave

looks great
a few little points....

the only line you will need in the preamble is
        INCLUDE \masm32\include\masm32rt.inc

have a look inside that file to see what it includes for you   :bg

include \masm32\include\masm32rt.inc

.data?
pstr1 dd ?
pstr2 dd ?

.code

start:
    mov pstr1, input("Type any number: ", 62, " ")   
    invoke atodw, pstr1
    mov pstr1, eax
    xor eax, eax
    mov pstr2, input("Type another number: ", 62, " ")
    invoke atodw, pstr2
    add eax, pstr1
    mov pstr2, eax
    print str$(pstr2), " is the final sum", 13,10
    inkey
    exit

end start


you only need 1 "start:" and 1 "end start"

while RET probably works, ExitProcess is the correct way to terminate
        INVOKE  ExitProcess,0
the masm32 package has an "exit" macro that saves a little typing