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?
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
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
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
the sval or uval macro may be used
refer to the help files.....
masm32\help\hlhelp.chm
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?
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.
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....
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.
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
This is your problem,
invoke StdOut, addr pstr1
You are getting the ADDRESS of an ADDRESS.
Try it without the ADDR.
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'
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.
The next step is to filter users input to make sure that it is a digit 0 to 9 & not some other character :wink
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
Thanks for all advices guys.
Hutch - I'll pay more attemption while using functions that returns an address so i don't need to pass their address as if they already contain one inside
Dave - Thanks for your remarks. You know, it was almost 4 am, i was almost blacking out.
About the include lines, yes, it had more than needed, cause i was using macros from another libs, i just forgot to delete the line
same for the end start hehe
im gonna program a bit in C# now and more asm tomorrow night....thanks for your support guys, all of you!
:bg