Hello everyone,
Before starting, I'd like to say that I'm new on this forum, so I hope I've posted at the good place (if it's not the case, I'm sorry).
I took a look on the forum and I saw that this error appears frequently.
There's my code :
.386
.model flat, stdcall
.stack 1000h ; 4096-sized stack
option casemap : none ; differencies uppercase chars and lowercase ones
include msvcrt.inc
include masm32rt.inc
include masm32.inc
include masm32/m32lib/ltoa.asm ; without, error A2008 syntax error ltoa
includelib masm32.lib
includelib msvcrt.lib
includelib masm32rt.lib
.data
Hello db "Hello, World !", 13, 10 ; string ended with opcode 10 => endline
.data?
value db 64 dup (?)
; according to masm help (help/masmlib section conversion/atoi), 128 bytes are usually sufficient for input, a word is 2 bytes long
.code
main proc
invoke StdOut, addr Hello
invoke StdIn, addr value, 64
mov eax, atol value
add eax, 1
new db " "
ltoa new, addr value
invoke StdOut, addr new
main endp
end main
I found a topic where the error disappeared with the final 'end main', but it doesn't work for me.
That's the command line :
C:/masm32/bin/ml.exe /c /coff /Cp /nologo /I"C:/" /I"C:/masm32/include/" %file%
C:/masm32/bin/link.exe /subsystem:console /release /version:4.0 /libpath:"C:/" /libpath:"C:/masm32/lib" /out:%app%.exe %app%.obj
(file and app are <path>/<filename>.asm and <path>/<filename>, no problem with that)
I know there's print macro os MasmBasic lib by @jj2007 but to start, I'd like to understand I/O system in assembly before hide complexity (in another topic, I saw that a display requires 4 lines, right ?).
If it can help you, my final goal is to input two numbers, then display their sum.
But when I tried (with another program) to add two inputs, it displays the char corresponding to the sum of ASCII values.
How can I do ?
(I'm sorry if my English isn't very good, that's not my first language)
Hi an welcome on board.
.stack 1000h ; this is not used in Win32. Stack is set in the linker options if you need to.
include masm32rt.inc ; use this line by itself, it include the normal range of options.
You need a layout like this.
include \masm32\include\masm32rt.inc
.code
start:
; all of your code.
end start
So I write main: ... end main, and it works.
I don't need to change the stack's size, but I saw it on Internet.
The layout is correct because in the command line, I wrote /I"C:/masm32/include" and /I"C:/".
But ltoa doesn't seem to be recognized by the linker :
test.asm(24) : error A2008: syntax error : ltoa
test.asm(21) : error A2206: missing operator in expression
(Is this site based in Australia ? It's quite weird for m to see 06PM, because in France it's almost 11AM)
Welcome totosayen_cpp :thumbsup:
you need to put
new db " " in .data section
end strings with 0
"this is a string",0
and invoke ltoa in similar way you do with other PROC's like
Thank you for this welcome !
So, I did some changes (inputs a number, adds 1 and displays the result) :
.386
.model flat, stdcall
option casemap : none ; differencies uppercase chars and lowercase ones
include masm32rt.inc
includelib masm32rt.lib
.data
Hello db "Hello, World !", 13, 10, 0 ; string ended with opcode 10 => endline
new db " ", 0
.data?
value db 64 dup (?)
; according to masm help (help/masmlib section conversion/atoi), 128 bytes are usually sufficient for input, a word is 2 bytes long
.code
main:
invoke StdOut, addr Hello
invoke StdIn, addr value, 64
invoke atol, addr value
add value, 1
invoke ltoa, addr value, addr new
invoke StdOut, addr new
invoke ExitProcess, 0
end main
It compiles and links, but the output seems quite odd.
The program firstly displays "Hello, World !" followed by an endline, as expected.
Then, I input 8 and it ouputs 4206624.
Why this result ?
The "Hello World" is string data where 8 is an integer. Use a string conversion to make 8 into a displayable string.
You will fail miserably if you don't practice two things:
1. read the documentation carefully, and try to really understand it
2. comment your code thoroughly
include \masm32\include\masm32rt.inc
.data
Hello db "Hello, World !", 13, 10, 0 ; string ended with opcode 10 => endline
new db " ", 0
.data?
value dd ?
buffer db 64 dup (?) ; this buffer serves for what we type
; according to masm help (help/masmlib section conversion/atoi), 128 bytes are usually sufficient for input, a word is 2 bytes long
.code
main:
invoke StdOut, addr Hello
invoke StdIn, addr buffer, 64 ; get a string into the buffer
invoke atol, addr buffer ; convert to a long ("ascii to long")
mov value, eax ; the value was returned in eax
add value, 100 ; add something
invoke ltoa, value, addr new ; convert long to ascii
invoke StdOut, addr new ; print it
invoke ExitProcess, 0
end main
Hi Toto,
Here is a simple test piece that may be useful to you.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
.code
start:
call testbed ; call the testbed proc
exit ; the exit macro
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
testbed proc
LOCAL var1 :DWORD ; create local variables
LOCAL var2 :DWORD
LOCAL rslt :DWORD
mov var1, 100 ; load immediate values into variables
mov var2, 150
mov eax, var1 ; load 1st variable into EAX register
add eax, var2 ; add var2 to EAX
mov rslt, eax ; store EAX register in variable
print "Total = " ; display leading text
print ustr$(rslt),13,10 ; display calculation result
inkey ; pause to view the output
ret
testbed endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
Thank you @jj2007, I've read masm32/help/masmlib.chm (conversions/atol) and it doesn't (at least for me) say where the result is stored.
I'm sorry and I'll try to search more the next time.
I'm trying this to input the values :
include masm32rt.inc
.data
Hello db "Hello, World !", 13, 10, 0 ; string ended with opcode 10 => endline
input1 db "Input a number : " , 0
input2 db "Input another number : ", 0
plus db " + " , 0
equal db " = " , 0
endline db " ", 13, 10 , 0
.data?
resultInt dd ? ; result (integer) of the 2 numbers
resultStr db ? ; result (string) of the 2 numbers
; according to masm help (help/masmlib section conversion/atoi), 128 bytes are usually sufficient for input, a word is 2 bytes long
buffer1 db 64 dup (?) ; stores input 1
buffer2 db 64 dup (?) ; stores input 2
.code
inputValue proc text: dword, buffer: dword, value: dword
invoke StdOut, text ; displays text
invoke StdIn, buffer, sizeof buffer ; inputs string
invoke atol, buffer ; converts it into a signed number (dword)
add value, eax ; result stored in eax
mov eax, 0 ; resets eax
invoke StdOut, addr endline ; writes a new line to clean output
ret
inputValue endp
main:
; inputs the two values
invoke inputValue, addr input1, addr buffer1, addr resultInt
invoke inputValue, addr input2, addr buffer2, addr resultInt
; converts back value into a string
invoke ltoa, resultInt, addr resultStr
; displays the result
invoke StdOut, addr buffer1
invoke StdOut, addr plus
invoke StdOut, addr buffer2
invoke StdOut, addr equal
invoke StdOut, addr resultStr
invoke StdOut, addr endline
; ends the process
invoke ExitProcess, 0
end main
But it doesn't work as expected :
- The result is always 0 (if I remove addr of resultInt, it doesn't work; if I declare value param as a lpvoid compilation fails (undefined symbol))
- When displaying, the first buffer seems empty, whereas the second displays well (with the 2nd input)
invoke StdIn, buffer, sizeof buffer ; inputs string
Are you sure this is the right "sizeof buffer"? The local argument buffer is a DWORD, i.e. its size is 4 bytes :cool:
So, is there a way to "dereference" the pointer ?
In C we do :
type func(type* ptr) {
type val = *ptr;
}
How do you write invoke StdIn, buffer sizeof <dereferenced buffer> ?
invoke StdIn, buffer, sizeof buffer1 will work. If you insist on following the rules, add another argument to the proc:
inputValue proc text: dword, buffer: dword, value: dword, TheSize
invoke StdIn, buffer, TheSize
...
invoke inputValue, addr input1, addr buffer1, addr resultInt, sizeof buffer1
Better, avoiding misunderstandings:
inputValue proc text: dword, pBuffer: dword, value: dword, TheSize
invoke StdIn, pBuffer, TheSize
...
invoke inputValue, addr input1, addr buffer1, addr resultInt, sizeof buffer1
I added a paramater :
inputValue proc text: dword, buffer: dword, bufferSize: word, value: dword
...
invoke StdIn, buffer, bufferSize
...
inputValue endp
; main :
invoke inputValue, addr input1, addr buffer1, sizeof buffer1, addr resultInt
But I've the same problem (console log) :
Quote
***********
ASCII build
***********
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Input a number : 7
Input another number : 4
+ 4 = 0
Please post your complete code with comments.
invoke inputValue, addr input1, addr buffer1, sizeof buffer1, addr resultInt
invoke inputValue, addr input2, addr buffer2, sizeof buffer2, addr resultInt
; converts back value into a string
invoke ltoa, resultInt, addr resultStr
Sorry, that's the whole code :
include masm32rt.inc
.data
Hello db "Hello, World !", 13, 10, 0 ; string ended with opcode 10 => endline
input1 db "Input a number : " , 0
input2 db "Input another number : ", 0
plus db " + " , 0
equal db " = " , 0
endline db " ", 13, 10 , 0
.data?
resultInt dd ? ; result (integer) of the 2 numbers
resultStr db ? ; result (string) of the 2 numbers
; according to masm help (help/masmlib section conversion/atoi), 128 bytes are usually sufficient for input, a word is 2 bytes long
buffer1 db 64 dup (?) ; stores input 1
buffer2 db 64 dup (?) ; stores input 2
.code
inputValue proc text: dword, buffer: dword, bufferSize: word, value: dword
invoke StdOut, text ; displays text
invoke StdIn, buffer, bufferSize ; inputs string
invoke atol, buffer ; converts it into a signed number (dword)
add value, eax ; result stored in eax
mov eax, 0 ; resets eax
invoke StdOut, addr endline ; writes a new line to clean output
ret
inputValue endp
main:
; inputs the two values
invoke inputValue, addr input1, addr buffer1, sizeof buffer1, addr resultInt
invoke inputValue, addr input2, addr buffer2, sizeof buffer2, addr resultInt
; converts back value into a string
invoke ltoa, resultInt, addr resultStr
; displays the result
invoke StdOut, addr buffer1
invoke StdOut, addr plus
invoke StdOut, addr buffer2
invoke StdOut, addr equal
invoke StdOut, addr resultStr
invoke StdOut, addr endline
; ends the process
invoke ExitProcess, 0
end main
Ok, we are almost there:
resultInt dd ? ; result (integer) of the 2 numbers
resultStr db 100 dup(?) ; result (string) of the 2 numbers
(a single byte cannot hold a string)
inputValue proc text: dword, buffer: dword, bufferSize: word, pValue: dword
invoke StdOut, text ; displays text
invoke StdIn, buffer, bufferSize ; inputs string
invoke atol, buffer ; converts it into a signed number (dword)
mov edx, pValue ; you passed the address of resultInt
add [edx], eax ; add eax to result
; mov eax, 0 ; no use for that...
invoke StdOut, addr endline ; writes a new line to clean output
ret
inputValue endp
Now I'm learning from this forum
Thanks a lot @jj2007 :biggrin: all works fine now thanks to you :azn:
I've read a little tutorial which explained only a bit mov and print, so I tried to go a little further.
My favourite language is C++, and I wanted to try assembly to have an insight of how it works.
Good evening and maybe see you soon on the forum :-)
Good to see it works :thumbsup:
Re commenting your code, here is an example from As a software engineer, can you tell who developed a specific component in your team by looking at the style of coding? (https://www.quora.com/As-a-software-engineer-can-you-tell-who-developed-a-specific-component-in-your-team-by-looking-at-the-style-of-coding/answer/Ryan-Bland-5)
QuoteNow we take the length of array and add it to our counter. This is our offset, how we use it will be a surprise for later. I was thinking about calling the variable myOffet but I didn't want to seem so possessive about it. Actually we should probably break out this block into its own function for debugging but I'm still a little tired from lunch to do that right now.
Don't exaggerate :badgrin: