Hello, I'm trying to code in MASM and this is the result:
The Assembler gives out much errors, but I don't know how to fix them, since I'm a Newbie in ASM/MASM..
Could somebody fix my code and maybe explain me, what I did wrong, why it's wrong and how to do it right?
That's would be awesome, Thanks!
Rather than correcting every mistake, I'll point you in the right direction - then you can have fun fixing, plus you'll remember better in future :bdg
So, your main mistake is trying to use 2 memory accesses (variables and function parameters are memory access) in one instruction - x86 instructions generally only allow one memory access, so to do most things you'll need to go through a register..
Example:
cmp pos, len
is invalid because it attempts to use two parameters in the same instruction.
Solution:
mov eax, pos
cmp eax, len
"mov [myvar + pos], [abc + i]" and "test [abc + i], [abc + i]" are more examples... although they have the additional complication of trying to do even more things at once - happy hunting.
Just remember: one instruction should only do one thing (getting a variable is one thing, adding two numbers is one thing, copying a value is one thing..)
Thanks for your reply!
1.
mov [myvar + pos], [abc + i]
Can i write
mov eax, [abc + i]
mov [myvar + pos], eax
?
2.
mov eax, pos
cmp eax, len
Does
mov eax, pos
cmp len, eax
work, too?
PS: Do you know how "lea" works and what it does?
Thanks in advance..
EDIT:
Oh, wait..
In [abc + i] are 2 variables... so it won't work...
mov eax, i
[abc + eax]
Is this correct?
PS2: I can use ecx as iteration-variable, right?
But since it's a global register, i cannot use it as seperate cell in a recursion... is this so?
Quote from: n00b! on May 23, 2008, 04:53:18 PM
PS: Do you know how "lea" works and what it does?
Thanks in advance..
lea =
Load
Effective
Address
http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_6/CH06-1.html#HEADING1-136 That should explain what the instruction does.
Noob,
You have a few basic thingds to learn including the info that Tedd has told you. With assembler instructions you do not have in the normal sense "syntax errors", there are a published set of instructions (mnemonics) that directly represent hardware opcodes in the processor. With an Intel compatible notation assembler like MASM you have a notation for what is called the "complex addressing modes" which are normally enclosed in square brackets that have a very specific form dictated by the range of available opcodes in the processor.
Double memory operands (cmp mem, mem) do not have a corresponding opcode to assemble to, you must put at least one into a register to perform the comparison, data movement or operation.
The complex addressing modes cannot be used for memory variables added together like a high level language. They have a very clear set of rules in how you use them,
1. Base address (register or a leading displacement).
2. Index register.
3. Scaling factor for index register (1,2,4,8)
4. Displacement in bytes added to address.
You can get code like this from it.
mov eax, [ebx+ecx*4+64]
base address EBX plus index register ECX times scaling factor of 4 plus 64 bytes.
It takes a bit of work to get used to this complex addressing mode but the results are very fast and very clear once you get the swing of it.
LATER: Here is a quick rewrite that probably does what you were trying to do. There was a lot wrong with your original code so try and get the swing of what has been changed and why its been changed.
; ----------------------------------------
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
; -----------------------------------------
; don't put prototypes in the .CODE section
; -----------------------------------------
func1 PROTO :DWORD,:DWORD
func2 PROTO :DWORD
.DATA
txt db "txtdefgh", 0
mbttl db "Result",0
.DATA?
myvar db 64 dup (?)
.CODE
; ----------------------------------------
start:
push 4
push 0
call func1
invoke ExitProcess, 0
; ----------------------------------------
func1 proc pos:DWORD, len:DWORD
push esi
push edi
mov eax, len
cmp pos, eax
jg quit
mov esi, OFFSET txt ; the text address
mov edi, OFFSET myvar ; the destination buffer
mov ecx, LENGTHOF txt ; the length of the text
rep movsb ; copy txt to myvar
push OFFSET myvar ; push the result address
call func2 ; call procedure to display the result
quit:
pop edi
pop esi
ret
func1 endp
; ----------------------------------------
func2 proc s:DWORD
invoke MessageBox, NULL, s, OFFSET mbttl, MB_OK
ret
func2 endp
; ----------------------------------------
end start
Here is a variation tha shows some simple code that uses the complex addressing mode correctly.
; ----------------------------------------
func1 proc pos:DWORD, len:DWORD
push esi
mov eax, len
cmp pos, eax
jg quit
; ESI and EDX are two seperate BASE addresses.
mov esi, OFFSET txt ; the text address
mov edx, OFFSET myvar ; the destination buffer
or ecx, -1 ; use ECX as the INDEX
@@:
add ecx, 1 ; add 1 to the index each iteration of the loop
mov al, BYTE PTR [esi+ecx] ; copy byte from source
mov BYTE PTR [edx+ecx], al ; write it to destination
test al, al ; check if its an ASCII zero
jnz @B ; loop back if it is not
push OFFSET myvar ; push the result address
call func2 ; call procedure to display the result
quit:
pop esi
ret
func1 endp
; ----------------------------------------
The code starts with the two base addresses and increments the INDEX for both addresses, it tests at the end of the loop if the character is the ASCII zero terminator and exits the loop if it is.
Thank you all very much!!! :-)