flat assembler
Message board for the users of flat assembler.
![]() Goto page Previous 1, 2, 3, 4, 5, 6, 7 Next |
Author |
|
revolution 29 Mar 2012, 20:52
Code: pushfd mov eax,ecx add eax,edx add eax,13 popfd ; ... or instead use LEA lea eax,[ecx+edx+13] ;a single instruction to replace the five above |
|||
![]() |
|
cod3b453 29 Mar 2012, 22:59
@bubach: LEA is one of the most useful because it has the form "reg := reg+reg*scale+constant" allowing it to perform the triple addition revolution posted above as well as fast small constant multiplication (e.g. lea rax,[rax+2*rax] is equivalent to mul 3 but does not trash rdx); this can even be repeated for larger factors with the same benefits. In the case of 64bit code, it is the only instruction that can directly read rip (lea rax,[rip]), which is very useful when dealing with position independent code.
EDIT: I forgot to explicitly point out that while MOV performs the same address arithmetic as LEA, the result is the data at the address instead of the address. ---- All instructions have some kind of use at some point* but I'm sometimes disappointed with instructions such as pshuf for not having an encoding for a register imm8. (*though I think quite a few are pretty redundant now ![]() |
|||
![]() |
|
bubach 30 Mar 2012, 01:23
well, i'm not sure it produces the expected result but
Code: mov eax,[ecx+edx+13] assembles without error too. and data at the address versus the address point, i thought that was just as simple as using [] ? which you apparently do on LEA anyway? now flags is another subject, and i can see a reason for not wanting to mess that up, but unless i'm missing something, you can do the exact same thing with MOV in one line? the rip thing was a cool trick though, didn't know that. |
|||
![]() |
|
revolution 30 Mar 2012, 01:53
bubach wrote: well, i'm not sure it produces the expected result but |
|||
![]() |
|
bubach 30 Mar 2012, 02:14
yeah i guessed as much
![]() |
|||
![]() |
|
revolution 30 Mar 2012, 02:19
Instead of thinking about memory addresses, think of it as numerical computations. Let's say we want to compute x = y * 8 + z.
Naive way (ignoring eflags changes): Code: ;eax=y ;edx=z ;ecx=x (our answer) mov ecx,eax ;x = y shl ecx,3 ;x = y * 8 add ecx,edx ;x = y * 8 + z Code: ;eax=y ;edx=z ;ecx=x (our answer) lea ecx,[eax*8+edx] ;x = y * 8 + z |
|||
![]() |
|
Picnic 30 Mar 2012, 06:41
bubach, LEA can do a shift operation, two additions, and a move in just one instruction.
Example: Code: mov eax, ecx shl eax, 3 add eax, ebx sub eax, 1000 The LEA way: Code: lea eax, [ebx+8*ecx-1000] |
|||
![]() |
|
16bitPM 30 Mar 2012, 18:20
A somewhat simpler way to look at it is to see LEA as a 3-operand add:
Replace: MOV EAX,EBX ADD EAX,17 // ADD EAX,ESI With: LEA EAX,[EBX+17] // LEA EAX,[EBX+ESI] (reg1 = reg2 +constant // reg1=reg2+reg3) |
|||
![]() |
|
bubach 31 Mar 2012, 00:06
well, the thing is.. each one of these assembles fine ine fasw
Code: mov ecx,[eax*8+edx] ; same byte size as LEA, works fine to assemble mov eax, [ebx+8*ecx-1000] ; same byte size as LEA, assembles fine too So is there a problem with fasm, does it allow MOV instructions that isn't really supported? :s Becasue I'm still waiting for an example of LEA instruction where it won't assemble if I simply switch to MOV instead... :/ |
|||
![]() |
|
gunblade 31 Mar 2012, 01:23
As cod3b453 said:
Quote:
LEA carries out the arithmetic in the brackets, and puts the resulting ADDRESS in eax.. whereas MOV carries out the arithmetic in the brackes, and puts the DATA at the address calculated in eax.. In C(-ish) syntax it would be something similar to: Code: eax = ebx+8*ecx-1000; // Equivalent of: lea eax, [ebx+8*ecx-1000] eax = *(ebx+8*ecx-1000); // Equivalent of: mov eax, [ebx+8*ecx-1000] Last edited by gunblade on 31 Mar 2012, 01:33; edited 2 times in total |
|||
![]() |
|
tripledot 31 Mar 2012, 01:25
@bulbach:
Sooner or later you're going to try writing a program, and God help us all. Last edited by tripledot on 31 Mar 2012, 01:50; edited 1 time in total |
|||
![]() |
|
bubach 31 Mar 2012, 01:40
no thats not it, what i try to understand if, what if i do
Code: mov eax, ebx+8*ecx-1000 then it should be the same? maybe that's not valid syntax, in that case i see a point. drunk now too, hard to make sense of a lighter even.. hahah ![]() |
|||
![]() |
|
tripledot 31 Mar 2012, 01:48
Code: foo db 5 mov eax, foo ; eax = address of foo (could be anything, e.g. 48765098) mov eax, [foo] ; eax = value of foo (i.e. 5) lea eax, foo ; invalid syntax lea eax, [foo] ; same as "mov eax, foo", i.e. calculates the ADDRESS of foo, NOT its value mov eax, foo ; eax = address of foo (e.g. 230) add eax, 100 ; eax = address of foo + 100 (in this case 330) ; the VALUE of foo is still equal to 5!!! lea eax, [foo+100] ; same as the previous two instructions I can't be arsed anymore. |
|||
![]() |
|
ProphetOfDoom 31 Mar 2012, 02:12
I think the syntax of the LEA instruction is misleading because the square brackets imply dereferencing (like the C language's unary * operator) when really no dereferencing is taking place. No wonder people get confused.
|
|||
![]() |
|
bubach 31 Mar 2012, 02:18
ok thanks got it now. didn't kniw something like "mov eax, foo+100" was invalid sybtax. and i'm just getting more drunk, must stop posting before i annoy you to much
![]() |
|||
![]() |
|
16bitPM 31 Mar 2012, 10:43
tripledot wrote: @bulbach: LOL |
|||
![]() |
|
16bitPM 31 Mar 2012, 10:51
bubach wrote: ok thanks got it now. didn't kniw something like "mov eax, foo+100" was invalid sybtax. and i'm just getting more drunk, must stop posting before i annoy you to much It's not invalid syntax. If foo is a symbol then the assembler will do the calculation for you. You are misled because the different syntax: MOV EAX,EBX+4*ECX+1000H → INVALID!! Assembler can't know contents of registers. MOV EAX,[EBX+4*ECX+1000H] → VALID! CPU calculates address and dereferences that pointer. MOV EAX,offset_table + 100H → VALID! Assembler knows contents of symbol 'offset_table'. Now, internally, the CPU uses a so-called SIB-byte to encode this mode: Scale-Index-Byte offset. Suppose you want an instruction which ONLY did the calculation and move the result in your register... then you'd need a SIB-byte. Memory references are represented by square brackets which are coded with addressing mode bits and/or SIB-bytes. So... the easiest is just to retain the syntax with brackets. Hence the instruction: LEA EAX,[EBX+4*ECX+1000H] uses an SIB byte... but not to use it as a pointer! It may come as a relevation for you that earlier versions of MASM (prior to 6.0) implicitly changed LEA reg,[reg] to MOV reg,reg and LEA reg,[addr] to MOV reg,addr Hope this helps ![]() --- In the meantime in geekland: who *ever* used CMC? |
|||
![]() |
|
AsmGuru62 31 Mar 2012, 11:21
I always use CMC.
You see, I got a habit of making BOOLEAN functions return Carry Flag as a TRUE/FALSE indicator. And sometimes, CF is the opposite of a result, so I just CMC it before return. ![]() |
|||
![]() |
|
16bitPM 31 Mar 2012, 11:42
AsmGuru62 wrote: I always use CMC. If I would have a beard, I would scratch it. Weird that I didn't think of this ![]() |
|||
![]() |
|
Goto page Previous 1, 2, 3, 4, 5, 6, 7 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.