After displaying correctly:
Quote
label_a
label_b
the program freezes and gives a General Protection Fault.
I don't see an apparent reason. Any help?
Frank
.nolist
include \masm32\include\masm32rt.inc
.486
.code
start:
align 4
mov eax, label_a
mov ebx, label_b
mov ecx, label_c
mov edx, label_d
jmp eax
align 4
label_c:
print " label_c", 13, 10
jmp edx
align 4
label_a:
print " label_a", 13, 10
jmp ebx
align 4
label_d:
print " label_d", 13, 10
jmp end_test
align 4
label_b:
print " label_b", 13, 10
jmp ecx
align 4
end_test:
inkey chr$(13, 10, "--- ok ---", 13)
exit
end start
Probably the print macro modifies the GPRS.
Maybe I've to change something... ::)
it destroys EAX, ECX, and EDX (EAX is ok to destroy in your case)
in general, you can assume that masm32 lib and API functions preserve EBX, EBP, ESI, EDI
Quote from: dedndave on December 14, 2012, 05:49:38 AM
it destroys ECX
in general, you can assume that masm32 lib and API functions preserve EBX, EBP, ESI, EDI
I tried to push ecx before calling print macro but t didn't work.
I had to use a workaround to make it run:
align 4
mov eax, label_a
jmp eax
align 4
label_c:
print " label_c", 13, 10
mov edx, label_d
jmp edx
align 4
label_a:
print " label_a", 13, 10
mov ebx, label_b
jmp ebx
align 4
label_d:
print " label_d", 13, 10
jmp end_test
align 4
label_b:
print " label_b", 13, 10
mov ecx, label_c
jmp ecx
align 4
end_test:
But it is not the preinitialization I was looking for ::)
also - EDX :biggrin:
you have 4 labels - and you do not need to conform to the ABI
so, use EBX, EBP, ESI, and EDI :t
i try to keep EBP free for locals and the first one executed does not need to be preserved
so, for that one, use EAX, ECX, or EDX
Quote from: dedndave on December 14, 2012, 05:56:30 AM
also - EDX :biggrin:
you have 4 labels - and you do not need to conform to the ABI
so, use EBX, EBP, ESI, and EDI :t
i try to keep EBP free for locals and the first one executed does not need to be preserved
so, for that one, use EAX, ECX, or EDX
OK Dave, but I found a solution that suits my needs, I need esi and edi free:
align 4
mov eax, label_a
mov ebx, label_b
mov ecx, label_c
mov edx, label_d
push edx
push ecx
push ebx
jmp eax
align 4
label_c:
print " label_c", 13, 10
pop edx
jmp edx
align 4
label_a:
print " label_a", 13, 10
pop ebx
jmp ebx
align 4
label_d:
print " label_d", 13, 10
jmp end_test
align 4
label_b:
print " label_b", 13, 10
pop ecx
jmp ecx
align 4
end_test:
:P
.nolist
include \masm32\include\masm32rt.inc
.486
.code
align 4
start:
push label_d
push label_c
push label_b
push label_a
retn
align 4
label_c:
print " label_c", 13, 10
retn
align 4
label_a:
print " label_a", 13, 10
retn
align 4
label_d:
print " label_d", 13, 10
jmp end_test
align 4
label_b:
print " label_b", 13, 10
retn
align 4
end_test:
inkey chr$(13, 10, "--- ok ---", 13)
exit
end start
Interesting Dave :icon_exclaim:
So with retn I pop a value and jump there, as it looks like.
I never used this solution. Thanks for the hint :t
And, as usual here it is your note:
http://masm32.com/board/index.php?action=dlattach;topic=1046.0;attach=874;image
i have seen another method that might interest you, depending on what you are doing
that is to use "command lists"
the beauty of this is that you can make different lists for different uses
there are numerous variations on this, but here is the basic idea....
.DATA
list1 dd label_a,label_b,label_c,label_d,label_c,label_b,label_a,end_test
.CODE
start:
mov ebx,offset list1
jmp dword ptr [ebx]
align 4
label_c:
add ebx,4
print " label_c", 13, 10
jmp dword ptr [ebx]
align 4
label_a:
add ebx,4
print " label_a", 13, 10
jmp dword ptr [ebx]
align 4
label_d:
add ebx,4
print " label_d", 13, 10
jmp dword ptr [ebx]
align 4
label_b:
add ebx,4
print " label_b", 13, 10
jmp dword ptr [ebx]
align 4
end_test:
inkey chr$(13, 10, "--- ok ---", 13)
exit
end start
EDIT - added "dword ptr" to the branches
if you wanted to, you could put the string pointers in the list and step by 8 :P
another way to go is to have a single dword variable that holds a branch vector
each step in the code can modify the vector for the next branch
Quote from: dedndave on December 14, 2012, 06:22:47 AM
i have seen another method that might interest you, depending on what you are doing
that is to use "command lists"
the beauty of this is that you can make different lists for different uses
there are numerous variations on this, but here is the basic idea....
.DATA
list1 dd label_a,label_b,label_c,label_d,label_c,label_b,label_a,end_test
.CODE
start:
mov ebx,offset list1
jmp dword ptr [ebx]
align 4
label_c:
add ebx,4
print " label_c", 13, 10
jmp dword ptr [ebx]
align 4
label_a:
add ebx,4
print " label_a", 13, 10
jmp dword ptr [ebx]
align 4
label_d:
add ebx,4
print " label_d", 13, 10
jmp dword ptr [ebx]
align 4
label_b:
add ebx,4
print " label_b", 13, 10
jmp dword ptr [ebx]
align 4
end_test:
inkey chr$(13, 10, "--- ok ---", 13)
exit
end start
EDIT - added "dword ptr" to the branches
Yes it is very interesting. Maybe it is called
jump list and
I considered it as a valid alternative to switch/case and the like.
If there are multiple choices with jumps as results of the choice
then it is the perfect faster alternative to slow compare opcodes.
At least this is what I foresee looking at the code. :icon_eek:
it implements a little cleaner if you use ESI and LODSD
but, you said you wanted to ues ESI for something else
Quote from: dedndave on December 14, 2012, 10:30:06 AM
it implements a little cleaner if you use ESI and LODSD
but, you said you wanted to ues ESI for something else
It doesn't mean I can't change my mind :lol:
INCLUDE \masm32\include\masm32rt.inc
.DATA
list1 dd label_a,label_b,label_c,label_d,label_c,label_b,label_a,end_test
.CODE
start:
mov esi,offset list1
lodsd
jmp eax
align 4
label_c:
print " label_c", 13, 10
lodsd
jmp eax
align 4
label_a:
print " label_a", 13, 10
lodsd
jmp eax
align 4
label_d:
print " label_d", 13, 10
lodsd
jmp eax
align 4
label_b:
print " label_b", 13, 10
lodsd
jmp eax
align 4
end_test:
inkey chr$(13, 10, "--- ok ---", 13)
exit
end start
You guys worry me with your register usage, if you properly comply with the Intel ABI (preserve EBX ESI EDI EBP and ESP and trash EAX ECX and EDX) you will never get into trouble. Do it wrong and you will keep getting mysterious crashes. (Voice crying in the wilderness etc ....)
Dave, the main reason why you make a deviant branching mechanism is for speed yet you are using an antique and really SSSLLLOOOOOOOWWWWWWWWW "lodsd" instruction that will kill any speed advantage with a dispatcher. This is DOS brain era yet Intel in manuals from early Pentiums upwards to current i3/5/7 hardware recommend against using LODS, MOVS etc ... without the REP(E) prefix.
in the grander scheme of things, i doubt the difference between
LODSD | JMP EAX
and
ADD ESI,4 | JMP [ESI]
is nearly as big as you think :P
if you put any kind of code in the little module, it will likely overshadow the difference
but, if you like, i can whip out Michael's timing macro and we can test it :biggrin:
Quote from: dedndave on December 14, 2012, 01:26:54 PM
in the grander scheme of things, ...
It's definitely a bit shorter ;-)
Intel(R) Celeron(R) M CPU 420 @ 1.60GHz (SSE3)
loop overhead is approx. 188/100 cycles
? cycles for 100 * lodsd & jmp
? cycles for 100 * add esi & jmp
30 bytes for lodsd & jmp
46 bytes for add esi & jmp
that's not the test we were talking about
there has to be some "signifigant" code in each module
nonetheless, here are my results...
Intel(R) Pentium(R) 4 CPU 3.00GHz (SSE3)
+19 of 20 tests valid, loop overhead is approx. 243/100 cycles
28529 cycles for 100 * lodsd & jmp
19006 cycles for 100 * add esi & jmp
28495 cycles for 100 * lodsd & jmp
18970 cycles for 100 * add esi & jmp
28514 cycles for 100 * lodsd & jmp
18981 cycles for 100 * add esi & jmp
i am going to call that 29 vs 19 cycles
if you put 500 cycles of code in each section, it becomes rather insignifigant
Quote from: jj2007 on December 14, 2012, 02:13:58 PM
It's definitely a bit shorter ;-)
But it's also cheating, because "ADD ESI,4 | JMP [ESI]" is not even vaguely equivalent to "LODSD | JMP EAX". Perhaps you meant "ADD ESI,4 | JMP [ESI-4]"?
Quote from: japheth on December 14, 2012, 04:58:27 PM
Quote from: jj2007 on December 14, 2012, 02:13:58 PM
It's definitely a bit shorter ;-)
But it's also cheating, because "ADD ESI,4 | JMP [ESI]" is not even vaguely equivalent to "LODSD | JMP EAX". Perhaps you meant "ADD ESI,4 | JMP [ESI-4]"?
It is, it is, just read the posts before writing. Don't be scared, it's plain assembler, not MasmBasic :icon_mrgreen:
And surprisingly, on my cheap Intel CPU it's even faster...
Intel(R) Celeron(R) M CPU 420 @ 1.60GHz (SSE3)
2033 cycles for 100 * lodsd & jmp
2132 cycles for 100 * add esi & jmpOn AMD instead, it's 12 vs 9 cycles for the five jumps:
AMD Athlon(tm) Dual Core Processor 4450B (SSE3)
12744 cycles for 100 * lodsd & jmp
9169 cycles for 100 * add esi & jmp
Quote from: jj2007 on December 14, 2012, 05:21:45 PM
It is, it is, ...
It is what? It is ... cheating? - or: It is ... equivalent? Try to express yourself clearly!
Quote
... just read the posts before writing.
Ok, I finally did - but it didn't help.
Quote
Don't be scared, it's plain assembler, not MasmBasic :icon_mrgreen:
Ok .. but it still looks awe.......some.
Quote from: japheth on December 14, 2012, 04:58:27 PM
"ADD ESI,4 | JMP [ESI]" is not even vaguely equivalent to "LODSD | JMP EAX"
Quote from: jj2007 on December 14, 2012, 05:21:45 PM
It is, it is, ...
Quote from: japheth on December 15, 2012, 01:21:56 AM
It is what? It is ... cheating? - or: It is ... equivalent? Try to express yourself clearly!
I am so sorry! What I meant is: "ADD ESI,4 | JMP [ESI]" is
not even vaguely fully equivalent to "LODSD | JMP EAX" in the context of the ten lines of plain assembly code posted above by Dave. Apologies for not expressing myself clearly - I'm not a native English speaker, y'know ;-)
the difference is that EAX gets destroyed :P
Quote from: dedndave on December 15, 2012, 02:51:15 AM
the difference is that EAX gets destroyed :P
How beautiful. Let's destroy something togheter :P
Quote
Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz (SSE4)
loop overhead is approx. 187/100 cycles
3153 cycles for 100 * lodsd & jmp
3000 cycles for 100 * add esi & jmp
3151 cycles for 100 * lodsd & jmp
3000 cycles for 100 * add esi & jmp
3149 cycles for 100 * lodsd & jmp
3003 cycles for 100 * add esi & jmp
30 bytes for lodsd & jmp
46 bytes for add esi & jmp
--- ok ---
It's about 5% difference. Not that much I suppose.