Can somebody give me an example of adding two numbers with assembly language in MASM32 ?
#include <stdio.h>
int main()
{
int firstNumber, secondNumber, sumOfTwoNumbers;
printf("Enter two integers: ");
// Two integers entered by user is stored using scanf() function
scanf("%d %d", &firstNumber, &secondNumber);
// sum of two numbers in stored in variable sumOfTwoNumbers
sumOfTwoNumbers = firstNumber + secondNumber;
// Displays sum
printf("%d + %d = %d", firstNumber, secondNumber, sumOfTwoNumbers);
return 0;
}
Hi sunshine33,
As far as i understood, you need to write a procedure to get number 1 and number 2 that we type. This procedure must convert each number to INTEGER32, REAL4, REAL8 or REAL10
format. I dont know what you want to do. After it we may sum it.
If integer32, we use add, if real we may use FPU fadd. To convert a string to real number format you may get a converter that i wrote. It is here elsewhere. Search.
After having the sum we need to use a converter real to string to print the result.
Good luck
deleted
That's easy, in purest Masm:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
SetGlobals firstNumber, secondNumber, sumOfTwoNumbers
Init
mov firstNumber, Val(Input$("First number:\t", "123"))
mov secondNumber, Val(Input$("Second number:\t", "321"))
add eax, firstNumber
mov sumOfTwoNumbers, eax
Inkey Str$("The sum of %i", firstNumber), Str$(" plus %i", secondNumber), Str$(" is %i", sumOfTwoNumbers)
EndOfCode
First number: 123
Second number: 321
The sum of 123 plus 321 is 444
Perhaps you should show us what you have coded so far...?
deleted
I gether the original poster wanted MASM, not C runtime or emulated basic, here is a very simple integer ADD in MASM.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.data?
value dd ?
.data
item dd 0
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey ; pause so you can see the result
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
mov eax, 1234 ; put integer into eax
add eax, 5678 ; add integer to eax
print str$(eax),13,10 ; display the result
ret ; return to caller
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
Quote
I gether the original poster wanted MASM, not C runtime or emulated basic
(https://www.dropbox.com/s/kggdix1vlj3fici/spam.png?dl=1) (https://en.wikipedia.org/wiki/Spam_(food))
deleted
:biggrin:
Have I missed something here ?
mov eax, 1234 ; put integer into eax
add eax, 5678 ; add integer to eax
Add two integers using a register ? Why the hell would you need MSVCRT to add 2 numbers.
Quote from: hutch-- on August 03, 2018, 11:00:46 AM
I gether the original poster wanted MASM, not C runtime or emulated basic
inkey ; pause so you can see the result
exit
print str$(eax),13,10 ; display the result
Right! He also wanted to read in a string from the console, and convert it to numbers.
Quote from: jj2007 on August 03, 2018, 08:34:35 AMPerhaps you should show us what you have coded so far...?
That's why I posted "pure Masm" :lol:
I might as well post too. :P
Ascii Adder. Directly adds two ascii integers, no matter the length (size) of the integers, well tested in a fibonacci generator - so that the limit is known to be far beyond capability of simple 32 or 64 bit registers. (and most calculators.)
Integer 1 (src1), integer 2 (src2), destination(dst) all have seperate buffers. credit due to jimg for showing a better way to implement what I was originally trying. 8)
ascii_adder proc src1:dword, src2:dword, dst:dword, lent:dword ;(src1, src2, dst are pointers to already allocated memory. lent is the length of the largest value to be summed)
local carrie:dword
push esi
push edi
push ebx
mov esi, src1
mov edi, src2
mov ebx, dst
mov ecx, lent
mov carrie, 0
top:
mov eax,0
mov al,byte ptr [esi+ecx-1]
mov dl,byte ptr [edi+ecx-1]
add al,dl
sub al, 30h
add eax, carrie
mov carrie, 0
cmp al, 39h
jbe @f
mov carrie, 1
sub al, 10
@@:
mov [ebx+ecx-1], al
dec ecx
cmp ecx, 0
jnz top
pop ebx
pop edi
pop esi
ret
ascii_adder endp
:biggrin:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
AddemUp PROTO STDCALL :DWORD, :DWORD
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey ; pause so you can see the result
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL num1 :DWORD
LOCAL num2 :DWORD
LOCAL pbuf :DWORD
LOCAL buff[128]:BYTE
push esi
; -----------
; load locals
; -----------
mov num1, 1234
mov num2, 5678
; -----------------
; call the add proc
; -----------------
push num2
push num1
call AddemUp
mov esi, eax
; -------------------------
; get output buffer address
; -------------------------
lea eax, buff
mov pbuf, eax
; --------------
; display result
; --------------
print cat$(pbuf,"The sum of ",str$(num1)," plus ",str$(num2)," = ",str$(esi),chr$(13,10))
pop esi
ret ; return to caller
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
AddemUp proc num1:DWORD,num2:DWORD
mov eax, [esp+4]
add eax, [esp+8]
ret
AddemUp endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
I was not thinking about msvcrt.dll, it is normally linked - like it or not. Even hutch's examples here will link with msvcrt.dll, even though nothing would make us expect that. It is easy to see that with dependency walker or another similar tool.
It is possible to make an .exe without linking to msvcrt.dll, although it will not make anything useful.
This is all it gets from MSVCRT.
Imp Addr Hint Import Name from msvcrt.dll - Not Bound
-------- ---- ---------------------------------------------------------------
00002018 111 _kbhit
0000201C CE _getch
Because it is such an uncritical operation, dumping it off to MSVCRT makes sense.
Attached the exe of my snippet above. With PEview, I can see Kernel, user, gdi, shell, comdlg, ole32 but no msvcrt.
However, José is right: Dependency walker shows that some of the OS dlls rely on msvcrt.
Here another tiny version. The key is that for sum two numbers in asm you need use the registers:
Something like this:
mov eax, [number1]
add eax, [number2]
What you can't do is (I guess this is your question in fact):
add [number1], [number2]
Here is my example and its result:
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE masm32.inc
INCLUDELIB kernel32.lib
INCLUDELIB masm32.lib
.DATA
number1 DD 442
number2 dd 22
msg db 11 dup(0) ; 11 for sum 10 to its begining (1 zero at the end)
.CODE
num2str proc
; In: eax, number value
; Out: eax, offset of value in string format
mov esi, offset msg + 10
mov ebx, 10
@Next:
dec esi
xor edx, edx
div ebx
or edx, 30h
mov byte ptr [esi], dl
or eax, eax
jnz @Next
mov eax, esi
ret
num2str endp
start:
mov eax, [number1]
add eax, [number2]
call num2str
invoke StdOut, eax
INVOKE ExitProcess, 0
END start
> SumaWM01
Result: 464
I attach it also.
deleted
Win10 64 bit has all sorts of unusual connections so I would not be surprised what calls what. If a system DLL calls MSVCRT you are not directly dependent as it is an OS based connection that was not in all earlier versions and may not be in future versions. As it is part of the OS, it can be called directly and it has been so from later version of Win95 onwards.
Quote from: hutch-- on August 03, 2018, 10:00:20 PM
Win10 64 bit has all sorts of unusual connections so I would not be surprised what calls what. If a system DLL calls MSVCRT you are not directly dependent as it is an OS based connection that was not in all earlier versions and may not be in future versions. As it is part of the OS, it can be called directly and it has been so from later version of Win95 onwards.
MSVCRT.DLL is considerd a OS DLL - user applications are not expected to use it.
User applications are expected to use the MSVCRXX.DLLs from VC++ redistributables, recently UCRTBASE.DLL and other confusing DLLs.
However, MSVCRT.DLL is used internally by the OS and also by devices drivers developers - it would a general debacle if it is removed.
All right, MASM32 users come to use it as well :t
Raymond Chen: (https://blogs.msdn.microsoft.com/oldnewthing/20140411-00/?p=1273)
QuoteAlthough MSVCRT.DLL has been an operating system DLL for a long time, and has been documented as off-limits to applications, there are still a lot of people who treat it as a C runtime delivery channel, and those programs create a lot of grief for the product team.
I love that: creates a lot of grief. That's exactly what I wish to the team - a small revenge for all the Windows bugs :P
Seriously: Of course, msvcrt.dll works just fine. What they really want is that we create applications that run only with the latest Windows versions. That's the most prominent reason for the msvcrXX DLL hell 8)
Thanks a lot for all the replies
I was looking for a program that asks me to enter numbers to add like this ,
(https://s22.postimg.cc/mp4ro1fmn/enter_2_numbers_to_add_c_assembly.png)
So which one of the above is the most appropriate MASM32 Assembly language code that does this ?
Jose,
As MSVCRT has been there for over 20 years, I have not seen a reason not to use parts of it. Much of it is not a lot of use to assembler programmers, the OS APIs can do an enormous number of tasks but if you want a function that it has, its cheap and easy to use and extends the range of what you can do for very little effort. It has been used in MASM32 since the late 90s and it works fine in 64 bit MASM as well.
As its a core DLL over a long time that I doubt they would try and change, using it makes sense, you can avoid the version specific addons to it that cause so much grief with dependent higher level languages by using the old and well tested version.
sunshine,
While various member were happy enough to try and help you out, you will have to write your own code. Have a look through the examples and see what best suits what you are after then write the code you want, no one here will do it for you.
Sorry about some basic questions again , I have only learned c in college
I am only beginning to learn Assembly language
I had to research a bit of assembly on Linux , MS DOS before i finally made up my mind to learn Assembly in MASM32 .
C code to enter two numbers and Add .
#include <stdio.h>
int main()
{
int firstNumber, secondNumber, sumOfTwoNumbers;
printf("Enter two integers: ");
// Two integers entered by user is stored using scanf() function
scanf("%d %d", &firstNumber, &secondNumber);
// sum of two numbers in stored in variable sumOfTwoNumbers
sumOfTwoNumbers = firstNumber + secondNumber;
// Displays sum
printf("%d + %d = %d", firstNumber, secondNumber, sumOfTwoNumbers);
return 0;
}
OK , i will try to find the appropriate examples from above myself
The include files in MASM32 can be a bit confusing for a beginner like me .
But , Thanks for all the support and examples
I wish i could seriously get a clearer picture of this code in Assembly language for a start ,
int firstNumber, secondNumber, sumOfTwoNumbers;
printf("Enter two integers: ");
// Two integers entered by user is stored using scanf() function
scanf("%d %d", &firstNumber, &secondNumber);
How do you do this in assembly language ?
Quoteprintf("Enter two integers: ");
My main problem right now is , i am not sure about the differences of these right now .
C runtime , emulated basic and MASM32
?
The rough distinction is that the C language has a number of callable libraries as well as DLLs which generally have overlapping functions. You use them in C at runtime thus C runtime libraries.
One of our members, JJ has designed an emulation of BASIC written in MASM thus emulated basic.
MASM is a direct assembler and the MASM32 SDK extends that with libraries and macros to help introduce people to assembler programming. The real action in MASM is coding in assembler instructions but as that is complicated to start with, the libraries and macros make it a lot easier to start with and with practice a lot faster to code.
Thanks for the reply
By nidud ,
; adding.asm
; assemble with: Asmc -pe adding.asm
;
include conio.inc
.code
main proc
local firstNumber, secondNumber, sumOfTwoNumbers;
_cputs("Enter two integers: ")
;; Two integers entered by user is stored using scanf() function
_cscanf("%d %d", &firstNumber, &secondNumber)
;; sum of two numbers in stored in variable sumOfTwoNumbers
mov eax,firstNumber
add eax,secondNumber
mov sumOfTwoNumbers,eax
;; Displays sum
_cprintf("\r\n%d + %d = %d\r\n", firstNumber, secondNumber, sumOfTwoNumbers)
xor eax,eax
ret
main endp
end main
; adding.asm
; assemble with: Asmc -pe adding.asm
;
.486
.model flat, c
option dllimport:<msvcrt>
printf proto :ptr, :vararg
scanf proto :ptr, :vararg
.code
main proc
local firstNumber, secondNumber, sumOfTwoNumbers;
printf("Enter two integers: ")
;; Two integers entered by user is stored using scanf() function
scanf("%d %d", &firstNumber, &secondNumber)
;; sum of two numbers in stored in variable sumOfTwoNumbers
mov eax,firstNumber
add eax,secondNumber
mov sumOfTwoNumbers,eax
;; Displays sum
printf("%d + %d = %d\n", firstNumber, secondNumber, sumOfTwoNumbers)
xor eax,eax
ret
main endp
end main
By jj2007 ,
include \masm32\MasmBasic\MasmBasic.inc ; download
SetGlobals firstNumber, secondNumber, sumOfTwoNumbers
Init
mov firstNumber, Val(Input$("First number:\t", "123"))
mov secondNumber, Val(Input$("Second number:\t", "321"))
add eax, firstNumber
mov sumOfTwoNumbers, eax
Inkey Str$("The sum of %i", firstNumber), Str$(" plus %i", secondNumber), Str$(" is %i", sumOfTwoNumbers)
EndOfCode
By hutch--
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.data?
value dd ?
.data
item dd 0
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey ; pause so you can see the result
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
mov eax, 1234 ; put integer into eax
add eax, 5678 ; add integer to eax
print str$(eax),13,10 ; display the result
ret ; return to caller
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
AddemUp PROTO STDCALL :DWORD, :DWORD
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey ; pause so you can see the result
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL num1 :DWORD
LOCAL num2 :DWORD
LOCAL pbuf :DWORD
LOCAL buff[128]:BYTE
push esi
; -----------
; load locals
; -----------
mov num1, 1234
mov num2, 5678
; -----------------
; call the add proc
; -----------------
push num2
push num1
call AddemUp
mov esi, eax
; -------------------------
; get output buffer address
; -------------------------
lea eax, buff
mov pbuf, eax
; --------------
; display result
; --------------
print cat$(pbuf,"The sum of ",str$(num1)," plus ",str$(num2)," = ",str$(esi),chr$(13,10))
pop esi
ret ; return to caller
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
AddemUp proc num1:DWORD,num2:DWORD
mov eax, [esp+4]
add eax, [esp+8]
ret
AddemUp endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
By zedd151 ,
ascii_adder proc src1:dword, src2:dword, dst:dword, lent:dword ;(src1, src2, dst are pointers to already allocated memory. lent is the length of the largest value to be summed)
local carrie:dword
push esi
push edi
push ebx
mov esi, src1
mov edi, src2
mov ebx, dst
mov ecx, lent
mov carrie, 0
top:
mov eax,0
mov al,byte ptr [esi+ecx-1]
mov dl,byte ptr [edi+ecx-1]
add al,dl
sub al, 30h
add eax, carrie
mov carrie, 0
cmp al, 39h
jbe @f
mov carrie, 1
sub al, 10
@@:
mov [ebx+ecx-1], al
dec ecx
cmp ecx, 0
jnz top
pop ebx
pop edi
pop esi
ret
ascii_adder endp
nidud's example is using C run time library , That one looks a bit easy to read and understand .
JJ2007's example is an emulation of basic written in MASM , can understand but still looks complicated
zedd151 's example is a bit hard to understand too at this level of understanding ,
hutch--'s example is MASM , looks the hardest to me ,
Only in the nidud's example the user is asked to enter numbers ?
the hard part of the problem is not adding two values together
nor is it even converting the result to an ASCII string and displaying it
the hard part is getting the two values from the user
in the earlier replies, they have used macros, subroutines, or libraries to accomplish this
it is a little bit involved to understand the inner workings of how this is accomplished under win-32
it is basically a two-part process:
1 - get the ASCII numeric string from the user
(what happens if the user enters a non-numeric value, or a value that is too large?)
2 - convert the value entered (an ASCII string) into a binary number to work with
(do we want to support real numbers or just integers - signed or unsigned?)
you can look at the code for the "val" macro" to see the guts of the code :t
once you have the two values...
mov eax,dwValue1
add eax,dwValue2 ;EAX = dwValue1 + dwValue2
now, it is time to convert the value to an ASCII numeric string and display it
again, a two-part process - and, again, you can examine the code to see how it works
the macro code may be found in \Masm32\Macros\Macros.asm
the masm32 library source code for individual modules may be found in \Masm32\M32Lib
sunshine,
If this is for a school assignment, you must follow your teacher guidelines.
Most schools follow the Irvine book and its way of doing things. Although there is much room for criticism against it and its method of doing things it really has a comprehensive SDK with ready made library routines for a lot of things including inputing integers or floats from the command line without using the C runtime.
In other words, if your teacher follows the Irvine book odds are that you will have to follow it. :(
Here's my example 100% masm source. Ask your teacher what is my punctuation. :bgrin:
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE masm32.inc
INCLUDELIB kernel32.lib
INCLUDELIB masm32.lib
cdMaxSize EQU 11
.DATA?
szNumber1 db cdMaxSize dup(?)
szNumber2 db cdMaxSize dup(?)
iNum dd ?
.DATA
szTxtNum1 db "Your first number: ", 0
szTxtNum2 db "Your second number: ", 0
szTxtSum db "Both sum: ", 0
number1 DD 442
number2 dd 22
msg db cdMaxSize dup(0)
.CODE
num2str proc uses ebx edx esi
; In: eax, number value
; Out: eax, offset of value in string format
mov esi, offset msg + cdMaxSize - 1
mov ebx, 10
@Next:
dec esi
xor edx, edx
div ebx
or edx, 30h
mov byte ptr [esi], dl
or eax, eax
jnz @Next
mov eax, esi
ret
num2str endp
str2num proc uses ebx ecx edx esi edi
; In: eax, offset to str_num
; out: eax, the number converted
mov edi, eax ; offset
mov eax, 0
mov ecx, cdMaxSize
repne scasb
jne @NoFound
sub edi, 2
sub ecx, cdMaxSize
neg ecx
mov ebx, 1 ; factor
mov esi, 0 ; Acumulative
@Next:
dec ecx
jl @Exit
xor eax, eax ; clear it
mov al, byte ptr [edi]
and al, 15 ; 2num
mul ebx
add esi, eax ; get into accumulative
mov eax, ebx ; increases factor
mov ebx, 10
mul ebx
mov ebx, eax
dec edi ; reset pointer
jmp @Next
@Exit:
mov eax, esi
@NoFound:
ret
str2num endp
start:
; Get the numbers in asciiz
invoke StdOut, offset szTxtNum1
invoke StdIn, offset szNumber1, cdMaxSize
invoke StdOut, offset szTxtNum2
invoke StdIn, offset szNumber2, cdMaxSize
; Convert to numbers and sum
mov eax, offset szNumber1
call str2num
mov ebx, eax
mov eax, offset szNumber2
call str2num
add ebx, eax
; Show the result
invoke StdOut, offset szTxtSum
mov eax, ebx
call num2str
invoke StdOut, eax
INVOKE ExitProcess, 0
END start
Executing it:
; >sumawm02
Your first number: 45
Your second number: 23
Both sum: 68
deleted
deleted
Quote from: sunshine33 on August 04, 2018, 12:09:38 AMHow do you do this in assembly language ?
Quoteprintf("Enter two integers: ");
Like this maybe?
include \masm32\include\masm32rt.inc
.code
start:
printf("Enter two integers:") ; needs console assembly and link
MsgBox 0, "That was easy, right?", "Hi Sunshine", MB_OK
exit
end start
You are coming from C, that's fine, you'll be comfortable with the CRT functions. Check the \Masm32\Help folder, it's full of goodies. To get a feeling how to set up a simple program, check the \Masm32\Examples folder. Open the *.asm sources in \Masm32\qEditor.exe, and see what they are doing. Attention for console applications you need "console assemble & link".
Re "emulated Basic": Hutch came from PowerBasic, I came from GfaBasic.
His version: print str$(eax), 13, 10
My version: Print Str$(eax), CrLf$
;)
Thanks for all the reply .
Quote from: dedndave on August 04, 2018, 01:19:07 AM
the hard part of the problem is not adding two values together
nor is it even converting the result to an ASCII string and displaying it
the hard part is getting the two values from the user
This is what i have been trying to figure out in pure Assembly language without using any c type syntax's
I would like to learn Assembly language with MASM32 a bit more seriously
Quote from: caballero on August 04, 2018, 01:39:46 AM
Here's my example 100% masm source. Ask your teacher what is my punctuation. :bgrin:
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE masm32.inc
INCLUDELIB kernel32.lib
INCLUDELIB masm32.lib
cdMaxSize EQU 11
.DATA?
szNumber1 db cdMaxSize dup(?)
szNumber2 db cdMaxSize dup(?)
iNum dd ?
.DATA
szTxtNum1 db "Your first number: ", 0
szTxtNum2 db "Your second number: ", 0
szTxtSum db "Both sum: ", 0
number1 DD 442
number2 dd 22
msg db cdMaxSize dup(0)
.CODE
num2str proc uses ebx edx esi
; In: eax, number value
; Out: eax, offset of value in string format
mov esi, offset msg + cdMaxSize - 1
mov ebx, 10
@Next:
dec esi
xor edx, edx
div ebx
or edx, 30h
mov byte ptr [esi], dl
or eax, eax
jnz @Next
mov eax, esi
ret
num2str endp
str2num proc uses ebx ecx edx esi edi
; In: eax, offset to str_num
; out: eax, the number converted
mov edi, eax ; offset
mov eax, 0
mov ecx, cdMaxSize
repne scasb
jne @NoFound
sub edi, 2
sub ecx, cdMaxSize
neg ecx
mov ebx, 1 ; factor
mov esi, 0 ; Acumulative
@Next:
dec ecx
jl @Exit
xor eax, eax ; clear it
mov al, byte ptr [edi]
and al, 15 ; 2num
mul ebx
add esi, eax ; get into accumulative
mov eax, ebx ; increases factor
mov ebx, 10
mul ebx
mov ebx, eax
dec edi ; reset pointer
jmp @Next
@Exit:
mov eax, esi
@NoFound:
ret
str2num endp
start:
; Get the numbers in asciiz
invoke StdOut, offset szTxtNum1
invoke StdIn, offset szNumber1, cdMaxSize
invoke StdOut, offset szTxtNum2
invoke StdIn, offset szNumber2, cdMaxSize
; Convert to numbers and sum
mov eax, offset szNumber1
call str2num
mov ebx, eax
mov eax, offset szNumber2
call str2num
add ebx, eax
; Show the result
invoke StdOut, offset szTxtSum
mov eax, ebx
call num2str
invoke StdOut, eax
INVOKE ExitProcess, 0
END start
Executing it:
; >sumawm02
Your first number: 45
Your second number: 23
Both sum: 68
When i tried to Assemble it in MASAM32 SDK , its giving me errors .
Which assembler do you use ?
There are no paths in the source code for the includes and libraries. You need to "make" method to build it.
deleted
Quote from: sunshine33 on August 04, 2018, 10:46:08 PMWhen i tried to Assemble it in MASAM32 SDK , its giving me errors.
- replace the include etc lines with
include \masm32\include\masm32rt.inc Masm32 has hard-coded paths. That is old-fashioned but very, very efficient. Read the masm32rt.inc file to understand.
In particular:
include \Masm32\include\windows.inc ; correct! path relative to the source's path, no unnecessary SHOUTING, perfect!
INCLUDE C:\Masm32\include\windows.inc ; BAD, assumes that the user uses drive C:
INCLUDE kernel32.inc ; BAD, assumes that the user uses environment variables
- replace num2str with @num2str (3x)
Caballero has used the name of a Masm32 SDK macro for a proc. That won't work, so num2str needs a new name.
Oh, and btw: "its giving me errors" is not an acceptable way to ask for help. You post the exact error messages including the line numbers.
> When i tried to Assemble it in MASAM32 SDK , its giving me errors
> Which assembler do you use ?
The "bat" file had also the compilation of another program (ConWM01), my fault. You only need these two lines, assuming that your compiler is in C:\masm32, compiling "SumaWM02.asm" from its folder:
C:\masm32\bin\ml.exe /c /coff /Cp /IC:\masm32\Include SumaWM02.asm
C:\masm32\bin\link.exe /SUBSYSTEM:CONSOLE /LIBPATH:c:\masm32\lib SumaWM02
The compiler I use is masm
If its the MASM32 SDK you are using, use its methods to get up and going. Custom builds are fine once you know your way around but while you are learning how it works, use the stuff provided as it is designed to be easy enough to use.
It is the MASM32 SDK what I am using, no custom build. My choice is to tell the compiler/linker where are the includes/libraries, not in the source. This way you only have to change the bat in the case the includes/libraries are in other location.
I have put all what is needed in my first post. Please, download and tell me if everything goes right.
My god , i finally made it work :greenclp:
(https://s33.postimg.cc/q0eki8q65/myfirstasmprogramerror.png)
Quoteinclude windows.inc
This is included so that we can used predefined constants and
structures. It is a master include file that defines all the
Windows data types, function calls, data structures, and constant
identifiers so you can refer to them by name in your code. Of
note here is that windows.inc defines NULL and MB_OK so that
these can be used by name to make the code more readable.
include kernel32.inc
This contains the prototypes for functions in kernel32.dll
include user32.inc
This contains the prototypes for functions in user32.dll
includelib kernel32.lib
It is required to invoke ExitProcess api.
Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658%28v=vs.85%29.aspx
includelib user32.lib
It is required to invoke MessageBox api.
Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505%28v=vs.85%29.aspx
.data
MessageText db "Hello World",0
Defining a array of bytes containing string "Hello World". This is
the message we want to display.
CaptionText db "Welcome to ASM",0
Defining a array of bytes containing string "Welcome to ASM". This
is the title of the window.
Note: I have null terminated both the strings.
Reason?? Left for the home work and try yourself.
.code
Start:
invoke MessageBox,NULL,Addr MessageText,Addr CaptionText,MB_OK
Invoke is similar to call function except one difference. Invoke
does type checking of parameters whereas call does not. So, to
invoke to work, we have included *.inc file for the respective
.dll as *.inc file contain the prototypes for functions in .dll
MessageBox api:
This api is defined in user32.dll. It has 4 Parameters:
hWnd [in, optional]
Type: HWND
A handle to the owner window of the message box to be created. If
this parameter is NULL, the message box has no owner window.
lpText [in, optional]
Type: LPCTSTR
The message to be displayed. If the string consists of more than
one line, you can separate the lines using a carriage return
and/or linefeed character between each line.
lpCaption [in, optional]
Type: LPCTSTR
The dialog box title. If this parameter is NULL, the default
title is Error.
uType [in]
Type: UINT
We have passed the following 4 arguments:
NULL - there is no parent window.
addr MessageText - address of our text string.
addr CaptionText - address of our caption.
MB_OK - one of a set of pre-defined styles.
Addr
This give the address of the string. For above, address of
MessageText and CaptionText.
invoke ExitProcess,0
This calls the ExitProcess with argument 0 i.e the return value.
This api is invoked to exit the program gracefully.
End Start
The only remaining problem , The program is exiting too fast :(
> My god , i finally made it work
It is not necessary include the path in the source if you tell it to the compiler/linker
> The only remaining problem , The program is exiting too fast
What exactly means that?
Before your exit of the program, use the macro "inkey". That stops the app until you press any key.
> It is not necessary include the path in the source if you tell it to the compiler/linker
There are many ways to build an executable, set the environment, add the paths to the ML and LINK lines but the best way to confuse a person learning is to flood them with options.
Which option if everything goes in a batch? I guess that the confusing comes from he uses a text editor with predefined options. IE, why am I going to use the batch he gave me? :greensml:
Quote from: hutch-- on August 05, 2018, 12:39:17 AM
Before your exit of the program, use the macro "inkey". That stops the app until you press any key.
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\masm32.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\masm32.lib
cdMaxSize EQU 11
.DATA?
szNumber1 db cdMaxSize dup(?)
szNumber2 db cdMaxSize dup(?)
iNum dd ?
.DATA
szTxtNum1 db "Your first number: ", 0
szTxtNum2 db "Your second number: ", 0
szTxtSum db "Both sum: ", 0
number1 DD 442
number2 dd 22
msg db cdMaxSize dup(0)
.CODE
num2str proc uses ebx edx esi
; In: eax, number value
; Out: eax, offset of value in string format
mov esi, offset msg + cdMaxSize - 1
mov ebx, 10
@Next:
dec esi
xor edx, edx
div ebx
or edx, 30h
mov byte ptr [esi], dl
or eax, eax
jnz @Next
mov eax, esi
ret
num2str endp
str2num proc uses ebx ecx edx esi edi
; In: eax, offset to str_num
; out: eax, the number converted
mov edi, eax ; offset
mov eax, 0
mov ecx, cdMaxSize
repne scasb
jne @NoFound
sub edi, 2
sub ecx, cdMaxSize
neg ecx
mov ebx, 1 ; factor
mov esi, 0 ; Acumulative
@Next:
dec ecx
jl @Exit
xor eax, eax ; clear it
mov al, byte ptr [edi]
and al, 15 ; 2num
mul ebx
add esi, eax ; get into accumulative
mov eax, ebx ; increases factor
mov ebx, 10
mul ebx
mov ebx, eax
dec edi ; reset pointer
jmp @Next
@Exit:
mov eax, esi
@NoFound:
ret
str2num endp
start:
; Get the numbers in asciiz
invoke StdOut, offset szTxtNum1
invoke StdIn, offset szNumber1, cdMaxSize
invoke StdOut, offset szTxtNum2
invoke StdIn, offset szNumber2, cdMaxSize
; Convert to numbers and sum
mov eax, offset szNumber1
call str2num
mov ebx, eax
mov eax, offset szNumber2
call str2num
add ebx, eax
; Show the result
invoke StdOut, offset szTxtSum
mov eax, ebx
call num2str
invoke StdOut, eax
INVOKE ExitProcess, 0
END start
Sorry this is my first time with MASM32 SDK , Where do i add that code ?
> Where do i add that code ?
After you display the result.
Here is a test piece.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this console app with
"MAKEIT.BAT" on the PROJECT menu.
----------------------------------------------------- *
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL pbuf1 :DWORD ; allocate pointers
LOCAL pbuf2 :DWORD
LOCAL buff1[64]:BYTE ; allocate buffers
LOCAL buff2[64]:BYTE
LOCAL num1 :DWORD ; variable for numbers
LOCAL num2 :DWORD
LOCAL rslt :DWORD ; variable for result
lea eax, buff1 ; load address into 1st pointer
mov pbuf1, eax
lea eax, buff2 ; load address into 2nd pointer
mov pbuf2, eax
print "Enter a number "
invoke StdIn,pbuf1,64 ; get the first number from the console
print "Enter another "
invoke StdIn,pbuf2,64 ; get the second number from the console
mov num1, val(pbuf1) ; convert input strings to numbers
mov num2, val(pbuf2)
mov eax, num1 ; add thhe two numbers
add eax, num2
mov rslt, eax ; store the result in a variable
print "The total = "
print str$(rslt),13,10 ; display the result
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
A suggestion.
Use .686p instead of .386 and you can use later instructions.
:P
> IE, why am I going to use the batch he gave me?
Lets look at a few options.
1. Set the paths in the OS. Tough if you want multiple environments.
2. Set the paths using "set" in the build batch file. Fine if you already know how to do it.
3. Manually add the paths to the ML and LINK command lines if you are familiar with both.
This is how you confuse someone who is starting to learn assembler, flood them with options.
I would like to continue using this code to learn assembly language in MASM32 SDK ,
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\masm32.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\masm32.lib
cdMaxSize EQU 11
.DATA?
szNumber1 db cdMaxSize dup(?)
szNumber2 db cdMaxSize dup(?)
iNum dd ?
.DATA
szTxtNum1 db "Your first number: ", 0
szTxtNum2 db "Your second number: ", 0
szTxtSum db "Both sum: ", 0
number1 DD 442
number2 dd 22
msg db cdMaxSize dup(0)
.CODE
num2str proc uses ebx edx esi
; In: eax, number value
; Out: eax, offset of value in string format
mov esi, offset msg + cdMaxSize - 1
mov ebx, 10
@Next:
dec esi
xor edx, edx
div ebx
or edx, 30h
mov byte ptr [esi], dl
or eax, eax
jnz @Next
mov eax, esi
ret
num2str endp
str2num proc uses ebx ecx edx esi edi
; In: eax, offset to str_num
; out: eax, the number converted
mov edi, eax ; offset
mov eax, 0
mov ecx, cdMaxSize
repne scasb
jne @NoFound
sub edi, 2
sub ecx, cdMaxSize
neg ecx
mov ebx, 1 ; factor
mov esi, 0 ; Acumulative
@Next:
dec ecx
jl @Exit
xor eax, eax ; clear it
mov al, byte ptr [edi]
and al, 15 ; 2num
mul ebx
add esi, eax ; get into accumulative
mov eax, ebx ; increases factor
mov ebx, 10
mul ebx
mov ebx, eax
dec edi ; reset pointer
jmp @Next
@Exit:
mov eax, esi
@NoFound:
ret
str2num endp
start:
; Get the numbers in asciiz
invoke StdOut, offset szTxtNum1
invoke StdIn, offset szNumber1, cdMaxSize
invoke StdOut, offset szTxtNum2
invoke StdIn, offset szNumber2, cdMaxSize
; Convert to numbers and sum
mov eax, offset szNumber1
call str2num
mov ebx, eax
mov eax, offset szNumber2
call str2num
add ebx, eax
; Show the result
invoke StdOut, offset szTxtSum
mov eax, ebx
call num2str
invoke StdOut, eax
INVOKE ExitProcess, 0
END start
But i cant get this program to work with inkey
It says
error A2008 : syntax error : inkey
It will work perfectly if you follow the handful of instructions I gave you in reply #38 (http://masm32.com/board/index.php?topic=7321.msg79915#msg79915).
inkey is one of the macros that get included with the one-liner
include \masm32\include\masm32rt.inc, which replaces everything before cdMaxSize EQU 11:
include \masm32\include\masm32rt.inc
cdMaxSize EQU 11
.DATA?
...
The masm32rt.inc one-liner is the standard way of writing an assembler program.
No special options or batch files required, just pick the "Console assemble & link" menu in \masm32\qEditor.exe, and it will build your program.
In case you still have doubts where to place the inkey:
invoke StdOut, eax
inkey " - it works, hooray!!!" INVOKE ExitProcess, 0
Quote from: hutch-- on August 05, 2018, 12:43:15 AMthe best way to confuse a person learning is to flood them with options.
:t
It worked :greenclp:
Thanks jj2007
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE \masm32\include\masm32rt.inc
cdMaxSize EQU 11
.DATA?
szNumber1 db cdMaxSize dup(?)
szNumber2 db cdMaxSize dup(?)
iNum dd ?
.DATA
szTxtNum1 db "Your first number: ", 0
szTxtNum2 db "Your second number: ", 0
szTxtSum db "Both sum: ", 0
number1 DD 442
number2 dd 22
msg db cdMaxSize dup(0)
.CODE
@num2str proc uses ebx edx esi
; In: eax, number value
; Out: eax, offset of value in string format
mov esi, offset msg + cdMaxSize - 1
mov ebx, 10
@Next:
dec esi
xor edx, edx
div ebx
or edx, 30h
mov byte ptr [esi], dl
or eax, eax
jnz @Next
mov eax, esi
ret
@num2str endp
str2num proc uses ebx ecx edx esi edi
; In: eax, offset to str_num
; out: eax, the number converted
mov edi, eax ; offset
mov eax, 0
mov ecx, cdMaxSize
repne scasb
jne @NoFound
sub edi, 2
sub ecx, cdMaxSize
neg ecx
mov ebx, 1 ; factor
mov esi, 0 ; Acumulative
@Next:
dec ecx
jl @Exit
xor eax, eax ; clear it
mov al, byte ptr [edi]
and al, 15 ; 2num
mul ebx
add esi, eax ; get into accumulative
mov eax, ebx ; increases factor
mov ebx, 10
mul ebx
mov ebx, eax
dec edi ; reset pointer
jmp @Next
@Exit:
mov eax, esi
@NoFound:
ret
str2num endp
start:
; Get the numbers in asciiz
invoke StdOut, offset szTxtNum1
invoke StdIn, offset szNumber1, cdMaxSize
invoke StdOut, offset szTxtNum2
invoke StdIn, offset szNumber2, cdMaxSize
; Convert to numbers and sum
mov eax, offset szNumber1
call str2num
mov ebx, eax
mov eax, offset szNumber2
call str2num
add ebx, eax
; Show the result
invoke StdOut, offset szTxtSum
mov eax, ebx
call @num2str
invoke StdOut, eax
inkey
INVOKE ExitProcess, 0
END start
(https://s33.postimg.cc/xto2cf959/program_masm32_sdk.png)
:greenclp:
When using "include \masm32\include\masm32rt.inc", you don't need those lines above it, masm32rt.inc takes care
of .386, .model, option, etc...
-------------------------------------------
.386
.MODEL flat, stdcall
OPTION casemap :none
INCLUDE \masm32\include\masm32rt.inc
--------------------------------------------
:t
Just so you know what is in masm32rt.inc... (I removed comments for brevity here)
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
include \masm32\include\ole32.inc
include \masm32\include\msvcrt.inc
include \masm32\include\dialogs.inc
include \masm32\macros\macros.asm
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\msvcrt.lib
As you can see, it takes care of loading the listed include (.inc) files, and libraries (.lib) , as well as a more recent cpu (.486)
plus, it loads macros.asm, so you have more macros at your immediate disposal. Macros makes programming in assembler really easy.
Thank you caballero for the original code ,
Thank you zedd151 for explaining that ,
Suddenly i feel like i can learn this properly
:greenclp:
mov num1, val(pbuf1) ; convert input strings to numbers
mov num2, val(pbuf2)
What is "val"?
It's a macro. Look in ...\masm32\macros\macros.asm.
Actually ends up invoking the function crt__Xtoi(), where X can be either a for ANSI or w for Unicode (for "wide").
Quote from: deeR44 on July 26, 2022, 04:07:51 PM
What is "val"?
Quotemov num1, val(pbuf1) ; convert input strings to numbers
Thanks, guys,
I appreciate it!
Quote; add [number1], [number2]
;.data
;number1 DD 442
;number2 dd 22
mov eax, number1 ; get 1st argument
add eax, number2 ; add 2nd argument
printf ("\nResult: %u\n", eax)
My version of adding those two numbers from wayback.
So now do it where you get those numbers from the user (via text input). How would you do that?
I guess that the only problem with code of this type,
printf ("\nResult: %u\n", eax)
is you pull in the C runtime library and unless you are calling MSVCRT, your app just got a lot bigger.
alternative to read in string->convert to dword ->add ->convert to ascii
is perform a BCD add
http://www.ray.masmcode.com/BCDtut.html (http://www.ray.masmcode.com/BCDtut.html)
Quote from: hutch-- on July 27, 2022, 07:31:43 PM
I guess that the only problem with code of this type,
printf ("\nResult: %u\n", eax)
is you pull in the C runtime library and unless you are calling MSVCRT, your app just got a lot bigger.
include \masm32\include\masm32rt.inc
.code
start:
mov eax, 12345
invoke crt_printf, chr$("eax=%i"), eax
exit
end start
1024 bytes. What do you mean with "pull in the C runtime library"?
:biggrin:
> unless you are calling MSVCRT, your app just got a lot bigger.
C runtime library is used by C, a static library. :biggrin:
Quote from: hutch-- on July 27, 2022, 09:20:12 PM
:biggrin:
> unless you are calling MSVCRT, your app just got a lot bigger.
C runtime library is used by C, a static library. :biggrin:
masm32/64 have own static runtime library.
C don't always need crt and can work with bare win32 API and use Windows OS msvcrt.dll directly.
Quote from: jj2007 on July 27, 2022, 09:10:12 PM
include \masm32\include\masm32rt.inc
.code
start:
mov eax, 12345
invoke crt_printf, chr$("eax=%i"), eax
exit
end start
1024 bytes. What do you mean with "pull in the C runtime library"?
Doesn't the "crt" in
crt_printf() mean "C runtime"? (I know it's part of the MASM32 library.)
Timo is right, C can use either its native runtime, static libraries or it can call MSVCRT but when I see "printf" in masm code, I reasonably assume that its the C runtime, not the system DLL.
I've always used wsprintf(), which is a Win32 function.
Quote from: NoCforMe on July 28, 2022, 10:32:23 AM
I've always used wsprintf(), which is a Win32 function.
I always use masm32 "print" macro until recently I converted to GUI app with Catstr$ macro followed by invoke SendMessageA and/or invoke MessageBox...
very useful when simulating lots of prints to a big text GUI control
wsprintf()/MessageBox() are very useful for inline debugging.
Can't tell you how many times I've done something like this:
.data
BuffPtrFmt DB "The buffer pointer is %08X", 0
.code
Something PROC
LOCAL buffPtr:DWORD, buffer[256]:BYTE
... do some stuff w/pointer ...
... now we want to see where the pointer is pointing:
INVOKE wsprintf, ADDR buffer, OFFSET BuffPtrFmt, buffPtr
INVOKE MessageBox, NULL, ADDR buffer, NULL, MB_OK
I've got all that stuff memorized ...
Quote from: NoCforMe on July 29, 2022, 09:12:35 AM
wsprintf()/MessageBox() are very useful for inline debugging.
Can't tell you how many times I've done something like this:
I
can tell you how often I use
deb (http://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1019) :tongue:
See this file in a later post as a 'zip' file.
Just do it ! :biggrin:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm64\include64\masm64rt.inc
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
entry_point proc
LOCAL pbuf1 :QWORD
LOCAL buff1[128]:BYTE
LOCAL pbuf2 :QWORD
LOCAL buff2[128]:BYTE
LOCAL var1 :QWORD
LOCAL var2 :QWORD
mov pbuf1, ptr$(buff1)
mov pbuf2, ptr$(buff2)
conout "Enter an integer "
rcall StdIn,pbuf1,128
conout "Enter an integer "
rcall StdIn,pbuf2,128
mov var1, uval(pbuf1)
mov var2, uval(pbuf2)
mov rax, var2
add var1, rax
conout "The total of both integers = ",str$(var1),lf
waitkey
.exit
entry_point endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
Floating point version. :biggrin:
; «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
include \masm64\include64\masm64rt.inc
.code
; «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
entry_point proc
LOCAL pbuf1 :QWORD
LOCAL buff1[128]:BYTE
LOCAL pbuf2 :QWORD
LOCAL buff2[128]:BYTE
LOCAL var1 :REAL8
LOCAL var2 :REAL8
LOCAL rslt :REAL8
mov pbuf1, ptr$(buff1) ; get the pointer to the buffer
mov pbuf2, ptr$(buff2) ; get the pointer to the buffer
conout "Enter a floating point number "
rcall StdIn,pbuf1,128 ; get a floating point format string
conout "Enter a floating point number "
rcall StdIn,pbuf2,128 ; get a floating point format string
rcall atofp,pbuf1,ptr$(var1) ; convert string data to floating point
rcall atofp,pbuf2,ptr$(var2) ; convert string data to floating point
movsd xmm0, var1 ; load fp var into xmm0
movsd xmm1, var2 ; load fp var into xmm1
addsd xmm0, xmm1 ; add the two together
movsd rslt, xmm0 ; copy result into fp var
rcall fptoa,rslt,pbuf1 ; reuse pbuf1
conout "Floating point result = ",pbuf1,lf ; display total
waitkey
.exit
entry_point endp
; «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
end
How would I include a 'zip' file in a post?
Zip the file THEN post it.
That sounds easy enough. Thank you--I'll try it tomorrow.
"Attachments and other options"
Quote from: NoCforMe on July 27, 2022, 07:26:09 PM
So now do it where you get those numbers from the user (via text input). How would you do that?
Here is the program that inputs two integers, adds them together, and displays the result.
This time it's in 'zip' format and lines will line up nicely.
I downloaded it and built it but I don't know what input it requires. If I run the exe by itself, nothing happens, tried two numbers on the command line but itt does nothing, how do I input any numbers to it ?
While waiting, here is a simple 32 bit example of getting user input, converting it to DWORD integers, adding the two together then converting it back to string to display.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.data?
inp1 db 128 dup (?)
inp2 db 128 dup (?)
.data
pin1 dd inp1
pin2 dd inp2
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey "Press any key to exit ...."
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL var1 :DWORD
LOCAL var2 :DWORD
LOCAL rslt :DWORD
LOCAL obuf[32]:BYTE
; --------------
; Get user input
; --------------
print "Enter an integer "
invoke StdIn,pin1,128
print "Enter another "
invoke StdIn,pin2,128
; --------------
; ------------------
; display input data
; ------------------
print "The first integer = "
print pin1,13,10
print "The second integer = "
print pin2,13,10
; ------------------
; ------------------------------
; convert input strings to DWORD
; ------------------------------
invoke atodw,pin1
mov var1, eax
invoke atodw,pin2
mov var2, eax
; ------------------------------
; --------------------
; perform the addition
; --------------------
mov eax, var1
add eax, var2
; --------------------
; ------------------------------
; load the output buffer address
; ------------------------------
lea edx, obuf
mov rslt, edx
; -------------------------------------
; convert the result in eax to a string
; -------------------------------------
invoke dwtoa,eax,rslt
; -------------------------------------
; ------------------
; display the result
; ------------------
print "The total = "
print rslt,13,10
; ------------------
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
Quote from: hutch-- on August 02, 2022, 03:45:46 PM
I downloaded it and built it but I don't know what input it requires. If I run the exe by itself, nothing happens, tried two numbers on the command line but itt does nothing, how do I input any numbers to it ?
I ran the program and got this result:
C:\masm32\projects\AddTwoInts>addtwointegers
Type your number: 1234
***1234***
Number of input digits is: 4.
Type your number: 000016
***16***
Number of input digits is: 2.
Result: 1250
C:\masm32\projects\AddTwoInts>
The second number was preceded by spaces and a tab, then leading ASCII zeros, the number and, finally, some more spaces and tabs. The program eliminates this garbage.
Does your program include this stuff except the obvious that doesn't belong"
.NOLIST
include \masm32\include\masm32rt.inc
include \masm32\include\fpu.inc
includelib \masm32\lib\fpu.lib
include \masm32\include\winmm.inc
includelib \masm32\lib\winmm.lib
.LIST
; #########################################################################
.data
input_buffer db 128 DUP (0)
output_buffer db 128 DUP (0)
temp_buffer db 128 DUP (0)
ALIGN 4
string_size dd 0 ; size of a measured input string
valid_sum dd 0 ; sum of valid digits
nseed_ms dd 0 ; ms since windows started
input_handle dd 0 ; token returned by Windows
len_input dd 0 ; length of input file
number1 DD 442
; number2 dd 22
; #########################################################################
I loaded the 'zip' from my original post, extracted it, assembled it, and finally ran it producing the above result.
I downloaded the zip file, unzipped it, built it as a default console app and it built correctly. When I ran it nothing was displayed at the console. It did not respond to command line arguments so I don't know how to get any output from it.
Quote from: hutch-- on August 03, 2022, 02:14:06 PM
I downloaded the zip file, unzipped it, built it as a default console app and it built correctly. When I ran it nothing was displayed at the console. It did not respond to command line arguments so I don't know how to get any output from it.
It wasn't written to accept command line arguments as you can see in the source.
I have no idea why it doesn't run on your system. During development, I assembled this program and ran it
dozens of times. Sometimes with horrific results. But I always got some input questions. Which are:
"Type your number: ".
Your program worked for me. A mystery why Hutch can't seem to get it to run. Not a great program, but it does work.
OK, I got it to work, it helps if you zip the exe file with it and how to use it.
K:\add2>addtwointegers
Type your number: 160
***160***
Number of input digits is: 3.
Type your number: 140
***140***
Number of input digits is: 3.
Result: 300
K:\add2>
Quote from: deeR44 on August 02, 2022, 02:52:06 PMHere is the program that inputs two integers, adds them together, and displays the result.
This time it's in 'zip' format and lines will line up nicely.
Congrats, your first working MASM program :thumbsup:
OK, if that really is your first MASM program, then mazeltov. It's a good feeling, no?
Hi to all! answer is near the topic
ProcEntry PROCESSENTRY32 < 296, 0 >
how correct fill structure in data ?
align good idea when you multiple times use string to compare or big table of data
Quote from: NoCforMe on August 03, 2022, 04:30:55 PM
Your program worked for me. A mystery why Hutch can't seem to get it to run. Not a great program, but it does work.
It probably isn't a great program, but you didn't have to say so.
We expect great things of you in the future.
It was more a case of knowing how to use it. Once I worked that out, it runs fine and does the job.
Yes, the "royal we". Just a way of sending good wishes your way.
OK, so moving on from your "first" program (congrats again, BTW), I have a challenge for you. Your mission, should you choose to accept it, is to take this GUI (graphical user interface) program and complete it so it adds two numbers. Almost all of the work has been done for you.
The program presents the user with a window that has 2 input fields (which are Windows edit controls) that they can use to enter the two numbers, and a button they can click to compute the sum of the numbers. Everything has been done for you except for calculating the sum and displaying it. Hopefully this will be a fun challenge.
The source code is well-commented to guide you. There's a lot of stuff here to absorb, so you might want to just focus on that small part of the code you need to add. (It should take less than a dozen lines of code to finish this program.) You'll need to look up one function on MSDN (link provided both in the source and below). You'll need to access MSDN anyhow if you plan on doing any Win32 programming, so you might as well get used to it.
If you get stumped don't hesitate to ask questions.
Here's the source (included in the .zip here):
;===================================================================
; -- DeeR44test.asm --
;
; A teachable moment or two ...
;
; A note on names here:
; This code uses my conventions for naming stuff:
;
; o Global variables (those defined in the .data or .data? sections)
; are capitalized (e.g., "MainTitleText")
; o Local variables (those defined by LOCAL within subroutines)
; are lowercase (e.g., "num1")
; o Symbolic constants (defined with EQU) start with "$"
; (e.g., "$staticStyles")
;
; THIS IS BY NO MEANS A MASM REQUIREMENT! It's just the way I like to
; name things. I find it very useful to know what kind of item
; I'm dealing with by looking at its name.
; If you have a system that works better for you,
; by all means use it.
;===================================================================
; Use ".nolist" here to turn off listing:
; otherwise you'll get a ton of crap in
; the listing (.lst) file!
.nolist
include \masm32\include\masm32rt.inc
.list
; (be sure to turn the listing back on)
;============================================
; Defines, macros, prototypes, etc.
;============================================
WinMain PROTO :DWORD
; This defines the dimensions of our main window:
$mainWinWidth EQU 600
$mainWinHeight EQU 200
;===== Window styles: =====
; Change 1st 2 styles to "WS_OVERLAPPEDWINDOW" if you want a resizeable window:
; This window will only have a "close" button and will not be resizeable.
$mainWinStyles EQU WS_CAPTION or WS_SYSMENU or WS_CLIPCHILDREN or WS_VISIBLE
; All these styles must include the "WS_CHILD" value since these controls (windows)
; are being created as children of the "parent" window (our main window):
$staticStyles EQU WS_CHILD or WS_VISIBLE
; The ES_NUMBER style makes sure that the user can only type numeric digits into the
; edit control. See how Windows makes life easier for us? No need to validate their input.
$editStyles EQU WS_CHILD or WS_VISIBLE or ES_LEFT or WS_BORDER or ES_NUMBER
$buttonStyles EQU WS_CHILD or WS_VISIBLE or BS_CENTER
; These are the locations and dimensions of our controls (static, edit & button)
; given as symbolic constants using EQU. EQU does *not* allocate storage or define
; a variable: it simply associates a symbolic name (like "$ST1X") with a numeric
; (or other) value. They make a programmer's job a whole lot easier! Instead of
; having to hunt through the code to change, say, the X-position of the button.
; you can easily find it here near the top of your source file.
; 1st static control: "Enter one number:"
$ST1X EQU 40 ;X-position
$ST1Y EQU 40 ;Y-position
$ST1W EQU 130 ;width
$ST1H EQU 16 ;height
$ST1ID EQU 100 ;ID # (arbitrary but must be unique)
; 2nd static control: "Enter another number:"
$ST2X EQU 40
$ST2Y EQU 80
$ST2W EQU 150
$ST2H EQU 16
$ST2ID EQU 101
; 3rd static control: "Result:"
$ST3X EQU 300
$ST3Y EQU 80
$ST3W EQU 50
$ST3H EQU 16
$ST3ID EQU 102
; 4th static control (output field)
$ST4X EQU 360
$ST4Y EQU 80
$ST4W EQU 150
$ST4H EQU 16
$ST4ID EQU 1200
; 1st edit control:
$ED1X EQU 200
$ED1Y EQU 40
$ED1W EQU 80
$ED1H EQU 20
$ED1ID EQU 1201
; 2nd edit control:
$ED2X EQU 200
$ED2Y EQU 80
$ED2W EQU 80
$ED2H EQU 20
$ED2ID EQU 1202
; Button:
$Btn1X EQU 350
$Btn1Y EQU 40
$Btn1W EQU 120
$Btn1H EQU 24
$Btn1ID EQU 1203
;============================================
; HERE BE DATA
;
; Here's where data items actually get
; defined and allocated.
;============================================
.data
; This is used by the RegisterClass() function:
WC WNDCLASSEX < SIZEOF WNDCLASSEX, \
CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW, \
NULL, \ ;lpfnWndProc
NULL, \ ;cbClsExtra
NULL, \ ;cbWndExtra
NULL, \ ;hInstance
NULL, \ ;hIcon
NULL, \ ;hCursor
NULL, \ ;hbrBackground
NULL, \ ;lpszMenuName
NULL, \ ;lpszClassName
NULL > ;hIconSm
; Class names here. All Windows windows belong to a class. Here are
; their names. The first one (our window) can be named anything we like:
MainClassName DB "DeeR44", 0
; The following are predefined Windows class names for control windows:
StaticClassName DB "static", 0
EditClassName DB "edit", 0
ButtonClassName DB "button", 0
; Change the following item to whatever you want the window title to be:
MainTitleText DB "DeeR44 Testbed", 0
; Text for static controls. This is the text that will appear on screen:
Text1 DB "Enter one number:", 0
Text2 DB "Enter another number:", 0
Text3 DB "Result:", 0
ButtonText DB "Add the Numbers", 0
;============================================
; UNINITIALIZED DATA
;
; This is for data which is assigned no initial value.
; It saves space in the executable file: none of these
; items are actually in the .EXE file. They are created
; when the program is run and loaded into memory.
;============================================
.data?
; This is the "handle" to our main window. Handles are what Windows
; uses to keep track of windows (and other things, like pens,
; brushes, bitmaps, icons, etc., etc.).
MainWinHandle HWND ?
; These are the handles to our 2 edit controls so we can
; read their contents:
Edit1Handle HWND ?
Edit2Handle HWND ?
; Handle to the 3rd static text control,
; which is our output field:
Static3Handle HWND ?
;============================================
; CODE LIVES HERE
;============================================
.code
start: INVOKE GetModuleHandle, NULL
MOV WC.hInstance, EAX
INVOKE WinMain, EAX
INVOKE ExitProcess, EAX
;====================================================================
; Mainline proc
;====================================================================
WinMain PROC hInst:DWORD
LOCAL msg:MSG, wX:DWORD, wY:DWORD, gpRect:RECT
; Register class for parent window:
MOV WC.lpfnWndProc, OFFSET MainWindowProc
INVOKE GetStockObject, LTGRAY_BRUSH
MOV WC.hbrBackground, NULL
MOV WC.lpszClassName, OFFSET MainClassName
; If you wanted an icon to show @ upper-left corner of your window,
; you would load it here:
; INVOKE LoadIcon, hInst, 500 ; icon ID
; MOV WC.hIcon, EAX
MOV WC.hIcon, NULL ;No icon for us.
INVOKE LoadCursor, NULL, IDC_ARROW
MOV WC.hCursor, EAX
INVOKE RegisterClassEx, OFFSET WC
; The following code centers the window on the desktop:
INVOKE GetSystemMetrics, SM_CXSCREEN
MOV EDX, $mainWinWidth
CALL CenterDim
MOV wX, EAX
INVOKE GetSystemMetrics, SM_CYSCREEN
MOV EDX, $mainWinHeight
CALL CenterDim ;Call our function (see below).
MOV wY, EAX
; Create our main window:
INVOKE CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, OFFSET MainClassName,
OFFSET MainTitleText, $mainWinStyles, wX, wY, $mainWinWidth,
$mainWinHeight, NULL, NULL, hInst, NULL
MOV MainWinHandle, EAX
; Create our control windows:
; First, the static (text) controls:
; 1st static text control ("Enter one number:"):
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET StaticClassName, ;class name
OFFSET Text1, ;window title/text
$staticStyles, ;styles
$ST1X, ;X-pos
$ST1Y, ;Y-pos
$ST1W, ;width
$ST1H, ;height
MainWinHandle, ;parent window
$ST1ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
; 2nd static text control ("Enter another number:":
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET StaticClassName, ;class name
OFFSET Text2, ;window title/text
$staticStyles, ;styles
$ST2X, ;X-pos
$ST2Y, ;Y-pos
$ST2W, ;width
$ST2H, ;height
MainWinHandle, ;parent window
$ST2ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
; 3rd static text control ("Result:):
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET StaticClassName, ;class name
OFFSET Text3, ;window title/text
$staticStyles, ;styles
$ST3X, ;X-pos
$ST3Y, ;Y-pos
$ST3W, ;width
$ST3H, ;height
MainWinHandle, ;parent window
$ST3ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
; 4th static text control (our output field):
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET StaticClassName, ;class name
NULL, ;window text (NULL since we'll be setting the text here)
$staticStyles, ;styles
$ST4X, ;X-pos
$ST4Y, ;Y-pos
$ST4W, ;width
$ST4H, ;height
MainWinHandle, ;parent window
$ST4ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
MOV Static3Handle, EAX
; Now two edit controls. These are where the user types their input
; (the two numbers in this case):
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET EditClassName, ;class name
NULL, ;window title/text (nothing here)
$editStyles, ;styles
$ED1X, ;X-pos
$ED1Y, ;Y-pos
$ED1W, ;width
$ED1H, ;height
MainWinHandle, ;parent window
$ED1ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
; When CreateWindowEx() returns (assuming it succeeds), it gives us the
; handle to the newly-created window (all Win32 return values go into the
; EAX register). So we must store it to be able to use it later:
MOV Edit1Handle, EAX
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET EditClassName, ;class name
NULL, ;window title/text (nothing here)
$editStyles, ;styles
$ED2X, ;X-pos
$ED2Y, ;Y-pos
$ED2W, ;width
$ED2H, ;height
MainWinHandle, ;parent window
$ED2ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
MOV Edit2Handle, EAX
; Last, create our button:
INVOKE CreateWindowEx,
0, ;EXstyles (nothing here)
OFFSET ButtonClassName, ;class name
OFFSET ButtonText, ;window title/text
$buttonStyles, ;styles
$Btn1X, ;X-pos
$Btn1Y, ;Y-pos
$Btn1W, ;width
$Btn1H, ;height
MainWinHandle, ;parent window
$Btn1ID, ;menu/ID
hInst, ;instance handle
NULL ;param (nothing here)
; We don't need to store this control's handle since we look for its messages
; by ID ("Btn1ID"). See the MainWindowProc() below for more info.
; This is the Windows "message loop". Since this type of program is "event-driven"
; and not linear like old-school programs, we continuously monitor the message
; stream (using GetMessage() ) to look for our messages. Anytime the user
; interacts with our program, say by clicking on one of our controls, we get
; notified through these messages. See MainWindowProc() below to see how we
; handle these messages.
;============= Message loop ===================
msgloop:
INVOKE GetMessage, ADDR msg, NULL, 0, 0
TEST EAX, EAX ;EAX = 0 = exit
JZ exit99
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
JMP msgloop
; This code is reached when the program is about to close (because the user
; clicked on the "close" button on our window):
exit99: MOV EAX, msg.wParam
RET
; The program now closes, the window is destroyed, and life goes on ...
WinMain ENDP
;====================================================================
; Main Window Proc
;
; This is the "window proc" for our main window. Unlike the linear
; programming that you're used to, this is different, because
;
; WE NEVER CALL THIS CODE!
;
; Instead, Windows calls it. This is what's known as a "callback"
; function, meaning that the operating system (Windows) calls it for us.
; Specifically, it gets called anytime there's a Windows message in
; the message queue. We look at the messages that we're interested in
; and respond to them. The other ones we just ignore.
;
; The parameters to this type of function are always the same:
; o hWin is the handle to the window (MainWinHandle in this case)
; o uMsg is the Windows message
; o wParam and lParam are additional data items
; For instance, the WM_COMMAND message puts the ID of the
; control that generated the message in wParam
; (see the code for WM_COMMAND below at "do_command")\;
;
; Note that the parameters are always the same, but not their names: we can name them anything we
; want to, so long as they're the correct type (they're all DWORDs here) and in the correct order.
;====================================================================
MainWindowProc PROC hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
; LOCAL variables are variables that MASM creates on the stack, so we don't
; need to allocate space for them ourselves (using DB, DW, DD or whatever).
; Since they're LOCAL, that means that they can only be used within the
; "scope" of the subroutine they're in (MainWindowProc() here). They cannot
; be accessed outside of this procedure, unlike "global" variables (like
; any of the variables we define in our .data or .data? sections).
LOCAL num1:DWORD, num2:DWORD
; These are the messages that our program responds to. There are literally
; hundreds of possible Windows messages; these are the only ones we're
; interested in here:
MOV EAX, uMsg
CMP EAX, WM_COMMAND
JE do_command
CMP EAX, WM_CLOSE
JE do_close
dodefault:
; This is where we go when one of those hundreds of other messages comes
; through our code. This goes to the default Windows handling code, which
; takes care of everything from drawing the borders of our window to
; "painting" it:
INVOKE DefWindowProc, hWin, uMsg, wParam, lParam
RET
; This code is reached when we get a WM_COMMAND message, for instance when
; the user clicks on our "Add the Numbers" button:
do_command:
; The command code is a WORD in half of a DWORD, so we get only that part:
MOV AX, WORD PTR wParam
CMP AX, $Btn1ID ;Is this our button sending that message?
JNE dodefault ; No, so just do the default thing.
; It's our button all right, so go add the numbers:
;***************************************************************
; Here's where you get to do some coding! What I'm giving you is
; reading both of the edit fields and putting their values into
; 2 local variables (num1 and num2). Your job:
;
; o Add these two numbers together
; o Display the result in the output field provided.
;
; For that last thing I'll give you a clue: Look up the Win32 function
; SetDlgItemInt(). This will display the number in a control (window)
; as text, so you don't need to convert from binary to ASCII.
; HINT: Pretend that this window is a dialog window (it really isn't).
; Use the ID of the control (the 4th static text control in this case)
; as the control ID to that function.
;
; HINT HINT: The SetDlgItemInt() function is very similar to GetDlgItemInt()
; (but not identical--be careful!).
;
; Look up this function on MSDN at
; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdlgitemint
;****************************************************
INVOKE GetDlgItemInt, hWin, $ED1ID, NULL, FALSE
MOV num1, EAX
INVOKE GetDlgItemInt, hWin, $ED2ID, NULL, FALSE
MOV num2, EAX
;****************************************************
; Insert your code here!
;****************************************************
; When we're done, we return 0 (EAX = 0) to indicate that we
; handled this message:
XOR EAX, EAX
RET
; This code closes the window and causes the program to exit:
do_close:
INVOKE PostQuitMessage, NULL
MOV EAX, TRUE
RET
MainWindowProc ENDP
; This routine is used to center our window on the desktop window.
; It's not necessary, just some nice icing on the cake.
;====================================================================
; CenterDim
;
; Returns half screen dimension (X or Y) minus half window dimension
;
; On entry,
; EAX = screen dimension
; EDX = window dimension
;
; Returns:
; sdim/2 - wdim/2
;====================================================================
CenterDim PROC
SHR EAX, 1 ;divide screen dimension by 2
SHR EDX, 1 ;divide window dimension by 2
SUB EAX, EDX
RET ;Return w/# in EAX
CenterDim ENDP
END start
It may look complicated--it's certainly more complex than the simple "console" program you wrote--but it is definitely within your abilities to code in this style. As pointed out in comments in the code, this style of programming is completely different from the "linear" style you're used to (like those good old MS-DOS programs of yore). This is because Windows GUI programs are "event driven", which means that instead of going straight through a line of execution, the program path ends in a "message loop". This loop constantly receives messages from the operating system--say when the user moves the mouse, clicks on a control, types at the keyboard, or any of a hundred other actions--and dispatches them to your code. Your program looks for a certain subset of these messages and responds to them. In this example, the one important message is one called WM_COMMAND, which is sent when the user clicks on the Add the Numbers button. This lets us branch to the code that does this task, reading the two numbers, adding them and displaying them. Does that make sense?
You can run the attached executable to see what it looks like. It just won't add the numbers and display them until you complete it. There's also a "makefile" attached, which is just a MS-DOS batch file to assemble and link the program. Should work on your system, assuming you have MASM32 installed.
Here's the link (https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdlgitemint) to the MSDN article on SetDlgItemInt() which you'll need to complete the program.
Couple comments on this program: It works, but it's uglier than crap. Once you finish making it work, we can talk about how to make its appearance nicer.
I call this type of Windows program the "poor man's dialog". What I've created here is what I call a "fake dialog", since it behaves like a Windows dialog but it's totally created manually. If you eventually get more into GUI programming like this you'll probably want to look into using what's called a "resource editor" to create actual Windows dialogs; this makes it much easier to arrange things on-screen, line things up, size them correctly, etc. I had to tweak this by changing numbers to get it to look even this good (which is still crappy). But at this point in your career, that's just icing on the cake ...
Have fun!
Great work, NoCforMe :thumbsup:
(I wouldn't have the necessary patience to write such detailed code, so well commented - compliments!)
Yes, and not to toot my own horn here, but comments are so important to good programming practice.
The way I look at it, comments are not even really for some outsider looking at the code as much as they're for me, the poor slob who wrote that mess of code and is looking at it 2-3 years later trying to figure out what the hell it does!
:nie:
Helping people is a good thing, inflicting your own "good programming practice" on others is not, especially when its 1990 style MS-DOS "good programming practice".
Can we have a little less pontification ?
Quote from: NoCforMe on August 05, 2022, 08:15:47 AM
OK, so moving on from your "first" program (congrats again, BTW), I have a challenge for you. Your mission, should you choose to accept it, is to take this GUI (graphical user interface) program and complete it so it adds two numbers. Almost all of the work has been done for you.
A. I tried to download your 'zip' file and Windows Defender said "Deer44test.zip Couldn't download - Virus detected"
B. I have never done a Windows program with graphical "windows" in it. I played around with a window someone
else did some time ago, but that's about it.
C. I looked at your windows program in reply #95 and noted that it has 530 lines in it. I don't think that I understood
50 lines in it.
Quote from: NoCforMe on August 05, 2022, 09:28:26 AMThe way I look at it, comments are not even really for some outsider looking at the code as much as they're for me, the poor slob who wrote that mess of code and is looking at it 2-3 years later trying to figure out what the hell it does!
I know the problem - today I was fighting like hell with some old code that I had to fix :biggrin:
Very good explanation of the message loop :thumbsup:
; Main Window Proc
;
; This is the "window proc" for our main window. Unlike the linear
; programming that you're used to, this is different, because
;
; WE NEVER CALL THIS CODE!
;
; Instead, Windows calls it. This is what's known as a "callback"
; function, meaning that the operating system (Windows) calls it for us.
; Specifically, it gets called anytime there's a Windows message in
; the message queue. We look at the messages that we're interested in
; and respond to them. The other ones we just ignore.
Quote from: deeR44 on August 05, 2022, 10:35:05 AM
Quote from: NoCforMe on August 05, 2022, 08:15:47 AM
OK, so moving on from your "first" program (congrats again, BTW), I have a challenge for you. Your mission, should you choose to accept it, is to take this GUI (graphical user interface) program and complete it so it adds two numbers. Almost all of the work has been done for you.
A. I tried to download your 'zip' file and Windows Defender said "Deer44test.zip Couldn't download - Virus detected"
B. I have never done a Windows program with graphical "windows" in it. I played around with a window someone
else did some time ago, but that's about it.
Sorry 'bout that (though not my fault; it's the goddamn AV programs, which give us false positives on the code we write here all the time. Well-known problem, apparently with no good solution. I have similar problems with AVG.)
Fortunately you don't need the .zip archive. Copy that source to an .asm file. Then copy the source below to a batch (.bat) file which will assemble and link the program. Then you can go to town programming your first GUI app, if you're so inclined. Run the .exe as-is to see what you have.
This only requires a few lines of code on your part, so not as painful as it might look.
@echo off
\masm32\bin\ml /c /coff /Fl /Sg /Sn DeeR44test.asm
if errorlevel 1 goto errasm
\masm32\bin\link /SUBSYSTEM:WINDOWS DeeR44test.obj
if errorlevel 1 goto errlink
goto TheEnd
:errlink
echo _
echo Link error
goto TheEnd
:errasm
echo _
echo Assembly Error
goto TheEnd
:TheEnd
So what's " the goddamn AV programs,", I wonder?
I'm afraid to copy the .asm file after the scary message I got. Besides, I know less that nothing about doing
that sort of thing (with windows).
Don't worry, assembling that source won't hurt anything.
Antivirus programs (like Windows Defender in your case, AVG in mine) can be hypersensitive and interpret some of the constructs found in executables made with MASM32 as malicious viruses when they're not. Assembling and running that program won't hurt your computer, I promise. (Windows 7 here, I run stuff like this all the time, no harm whatsoever.) My code, which anyone can see for themselves, contains nothing but valid, documented Win32 functions, no undocumented calls or other sneaky stuff.
You could turn your antivirus off, but I wouldn't advise that.
Just out of curiosity, what flavor of Windows are you running?
Windows 11
You should be fine. Go ahead and "make" that program, run it, see what you get. Let us know.
deer,
If you are having problems with AV crap scanning your ZIP files, password the zip file and it will not access the content. As far as normal Windows UI programs, write them with a manifest AND version control block and most of the "donkey level" av scanners will not cause any problems.
Quote from: hutch-- on August 05, 2022, 12:03:58 PM
deer,
If you are having problems with AV crap scanning your ZIP files, password the zip file and it will not access the content. As far as normal Windows UI programs, write them with a manifest AND version control block and most of the "donkey level" av scanners will not cause any problems.
I don't know what "AV" crap is.
I don't know what a "UI" program is.
I don't know what a "manifest" is.
I don't know what a "version control block" is.
If this is just too much, I understand.
Quote from: deeR44 on August 05, 2022, 12:14:39 PM
Quote from: hutch-- on August 05, 2022, 12:03:58 PM
deer,
If you are having problems with AV crap scanning your ZIP files, password the zip file and it will not access the content. As far as normal Windows UI programs, write them with a manifest AND version control block and most of the "donkey level" av scanners will not cause any problems.
I don't know what "AV" crap is.
Like I explained: hypersensitive anti-virus programs.
QuoteI don't know what a "UI" program is.
More properly "GUI", graphical user interface, like most of the Windows programs you use (Word, Excel, web browser, etc.), as opposed to "console"-type apps like the one you just wrote that only display text in a "command" (MS-DOS-like) window.
QuoteI don't know what a "manifest" is.
Something you can apply to an executable program to alter its appearance or functionality. Don't sweat it for now. Will explain one if (and when) you finish your little challenge.
QuoteI don't know what a "version control block" is.
Again, don't sweat it. You don't need it at this point.
Thank you, NoCforMe! I appreciate it.
:thdn:
I don't know what "AV" crap is.
I don't know what a "UI" program is.
I don't know what a "manifest" is.
I don't know what a "version control block" is.
Any you are giving advice about "best programming practice" ?
We have rules about people pontificating in the Campus, misleading new members. Its not as if anyone here needs your advice, especially as its out of date, 1990 MS-DOS style coding in ignorance of many years of standard Windows User Interfaces.
Any you are giving advice about "best programming practice" ?
I DON'T KNOW WHAT YOU MEAN BY THIS.
We have rules about people pontificating in the Campus, misleading new members. Its not as if anyone here needs your advice, especially as its out of date, 1990 MS-DOS style coding in ignorance of many years of standard Windows User Interfaces.
I DON'T KNOW WHAT YOU MEAN BY THIS, EITHER.
I would not recommend that you sit up at night sobbing silently while brushing away the tears so you don't make a soggy spot on the carpet.
The idea that there is a "best programming practice" for anyone to pontificate about, runs into the personal variation of each programmer who writes code as they choose and no-one is going to dictate to them how they write code.
As far as rules, the Campus is a protected forum where new members or members learning assembler will not be subject to pontification by anyone.
> I DON'T KNOW WHAT YOU MEAN BY THIS.
Tuff ! :badgrin:
Quote from: hutch-- on August 08, 2022, 06:22:40 PM
The idea that there is a "best programming practice" for anyone to pontificate about, runs into the personal variation of each programmer who writes code as they choose and no-one is going to dictate to them how they write code.
I don't know why you keep mentioning "best programming practice".
His comments are aimed at me, not you. Don't you get that?
Don't sweat it. How are you coming on your programming challenge?
Quote from: NoCforMe on August 11, 2022, 12:02:39 PM
His comments are aimed at me, not you. Don't you get that?
Don't sweat it. How are you coming on your programming challenge?
I'm working on something having to do with timed events--hh.mm. Got to separate them and manipulate them separately. Not a big deal.
Sounds interesting. Post something here? Curious minds want to know.
Quote from: NoCforMe on August 11, 2022, 12:41:38 PM
Sounds interesting. Post something here? Curious minds want to know.
Will do. I'll start on that tomorrow. OK, that would be today, later.
Could not download your zip file. Windows said, "Couldn't download - Virus detected".
If its the zip file, "DeeR44test.zip", there is nothing wrong with it as I have downloaded it. You may need to change your security settings in Win11.