Hello everyone, I'm pretty new to assembler, so this might be really obvious.
Just as an exercise I tried to write a decimal to ascii converter but I keep getting this error: "/masm32/include/masm32.inc(402) : error A2005: symbol redefinition : RUN_SYNCH_PROCESS_EX". Obviously I can stop the error if I don't include masm32.inc but I need it. Here's the code:
.386
.MODEL flat, stdcall
include /masm32/include/kernel32.inc
includelib /masm32/inc/kernel32.lib
include /masm32/include/masm32.inc
includelib /masm32/lib/masm32.lib
.DATA
number1 DWORD 7845
string1 BYTE 10 DUP(?),0
D1_dtoa PROTO :DWORD, :DWORD
.CODE
start:
;invokes the main process
invoke D1_dtoa, number1, addr string1
;exits
invoke ExitProcess, 0
end start
D1_dtoa PROC num1:DWORD, dest1:DWORD
LOCAL num1 :DWORD
LOCAL dest1 :DWORD
;saves all the variables
push ebp
mov ebp, esp
push eax
push ebx
push ecx
push edx
push esi
push edi
;moves local variables into ebx and edi
mov ebx, num
mov edi, dest
;checks if it is negative or not, puts a minus sign if it is, a space if it isn't
;This should save the sign bit and apply it at the end, I'll fix this later
cmp ebx, 0
jge not_negative
mov edx, '-'
mov [edi], edx
jmp negative
not_negative:
mov edx, ' '
mov [edi], edx
negative:
inc edi
;Divide by 10 and put remainder in the low part of the string
; end when ecx = 0 or eax = 0, quit
mov ecx, 9
.WHILE ecx > 0
mov edx, 10
mov eax, ebx
idiv edx
.IF eax == 0
.BREAK
.ENDIF
sub esi, ecx
mov [esi], edx
add esi, ecx
dec ecx
.ENDW
; fill in the rest with zeros. This is dumb and I'll fix it later
mov edx, 0
.WHILE ecx > 0
sub esi, ecx
mov [esi], edx
add esi, ecx
dec ecx
.ENDW
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret
D1_dtoa ENDP
END
I know there are probably a lot of dumb things I did(like very little comments, and manually saving the registers), so if you see something that doesn't have to do with main question but is bad assembly practice, feel free to tell me.
I tried changing all my variable names(that's why they all have a number one in them) but that didn't solve the problem.
I don't know if it matters but I tired assembling with this command:
ml /c /coff test.asm
I'd really appricate some help.
Thanks :bg
Include windows.inc before any other includes
Thanks, that fixed that problem.
Unfortunately there seem to be another one. When I try to link it I get this error: "d.obj : error LNK2001: unresolved external symbol _D1_dtoa@8".
Here's the code with the changes:
.386
.MODEL flat, stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/kernel32.inc
includelib /masm32/lib/kernel32.lib
include /masm32/include/masm32.inc
includelib /masm32/lib/masm32.lib
.DATA
number1 DWORD 7845
string1 BYTE 10 DUP(?),0
D1_dtoa PROTO :DWORD, :DWORD
.CODE
start:
;invokes the main process
invoke D1_dtoa, number1, addr string1
;exits
invoke ExitProcess, 0
end start
D1_dtoa PROC num1:DWORD, dest1:DWORD
LOCAL num1 :DWORD
LOCAL dest1 :DWORD
;saves all the variables
push ebp
mov ebp, esp
push eax
push ebx
push ecx
push edx
push esi
push edi
;moves local variables into ebx and edi
mov ebx, num
mov edi, dest
;checks if it is negative or not, puts a minus sign if it is, a space if it isn't
;This should save the sign bit and apply it at the end, I'll fix this later
cmp ebx, 0
jge not_negative
mov edx, '-'
mov [edi], edx
jmp negative
not_negative:
mov edx, ' '
mov [edi], edx
negative:
inc edi
;Divide by 10 and put remainder in the low part of the string
; end when ecx = 0 or eax = 0, quit
mov ecx, 9
.WHILE ecx > 0
mov edx, 10
mov eax, ebx
idiv edx
.IF eax == 0
.BREAK
.ENDIF
sub esi, ecx
mov [esi], edx
add esi, ecx
dec ecx
.ENDW
; fill in the rest with zeros. This is dumb and I'll fix it later
mov edx, 0
.WHILE ecx > 0
sub esi, ecx
mov [esi], edx
add esi, ecx
dec ecx
.ENDW
; restore regisiters
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret
end D1_dtoa
END
I'm thinking it has to do with how I'm invoking procedures, I haven't done it a whole lot so I could easily be messing it up.
Thanks.
it is simpler to use the masm32rt.inc file for your preamble
as for the new error, you just need a prototype
get rid of all this stuff...
.386
.MODEL flat, stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/kernel32.inc
includelib /masm32/lib/kernel32.lib
include /masm32/include/masm32.inc
includelib /masm32/lib/masm32.lib
and replace it with this...
INCLUDE \masm32\include\masm32rt.inc
D1_dtoa PROTO :DWORD,:DWORD
take a look inside the \masm32\include\masm32rt.inc file to see what it does for you
Um...
you have
start:
...
...
...
end start
someproc proc
end someproc
end
Not correct
should be
start:
...
...
ExitProcess, 0
your procs here
end start
and to define the start and end of a proc it should be:
MyProc proc
MyProc endp
notice the endp for end proc
also, there is no need to preserve EAX, ECX, or EDX
these 3 registers are normally used to return result and/or status (especially EAX)
i try to use all 3 - even when i don't need them
in this case, you might return:
EAX = 0 if no errors occur, otherwise an error code
ECX = length of result
EDX = address of result
this makes it very convenient to use the function
Quote from: dedndave on August 14, 2011, 07:22:40 PM
it is simpler to use the masm32rt.inc file for your preamble
as for the new error, you just need a prototype
get rid of all this stuff...
.386
.MODEL flat, stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/kernel32.inc
includelib /masm32/lib/kernel32.lib
include /masm32/include/masm32.inc
includelib /masm32/lib/masm32.lib
and replace it with this...
INCLUDE \masm32\include\masm32rt.inc
D1_dtoa PROTO :DWORD,:DWORD
take a look inside the \masm32\include\masm32rt.inc file to see what it does for you
He already has a proto...
Make the changes in my post and all will work :bg
oh - so he does - lol
i didn't see it down there hidden away :P
we generally put PROTOtypes right after the INCLUDE's
then STRUCTures
then MACRO's
then EQUates
then DATA
Quote
it is simpler to use the masm32rt.inc file for your preamble
I was just thinking about making something like that because I was getting tired of typing all that in every time. Thanks, that should make it nicer.
@Gunner
That clears a lot up, I was pretty confused about how that was all structured. So basically the program will start running automatically after the first thing that is in the form <name>: and it will stop at "end" or if it hits a ExitProcess?
Quote
we generally put PROTOtypes right after the INCLUDE's
then STRUCTures
then MACRO's
then EQUates
then DATA
That was another thing I was confused about, I just randomly put PROTOs in and I wasn't sure if it mattered or not. That make sense.
Thanks guys!
well - those aren't hard-and-fast rules
it just helps the flow
for example, you may reference an invoked function inside a macro, so we define prototypes first
we may want some equates up there, also - so we re-arrange things a bit
you get the idea
quite often, for larger projects, the prototypes, structures, macros, and equates go into a project INC file
Yuppers, once you start working on a large project (or any size really) it is good to put everything in a separate inc file
All my .data goes in strings.inc, all .data? goes in data.inc, protos in protos.inc, structures in struct.inc etc... then you just include them as any other include file