The MASM Forum

General => The Campus => Topic started by: frktons on December 14, 2012, 05:30:07 AM

Title: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 05:30:07 AM
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

Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 05:38:05 AM
Probably the print macro modifies the GPRS.
Maybe I've to change something... ::)
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 14, 2012, 05:49:38 AM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 05:53:28 AM
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 ::)
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: 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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 06:00:45 AM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 14, 2012, 06:01:36 AM
.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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 06:11:00 AM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 06:17:53 AM
And, as usual here it is your note:

http://masm32.com/board/index.php?action=dlattach;topic=1046.0;attach=874;image
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: 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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 14, 2012, 06:30:21 AM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 09:29:19 AM
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:
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: 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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 14, 2012, 11:03:30 AM
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:
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 14, 2012, 12:04:47 PM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: hutch-- on December 14, 2012, 12:28:33 PM
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.
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 14, 2012, 01:26:54 PM
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:
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: jj2007 on December 14, 2012, 02:13:58 PM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 14, 2012, 02:55:52 PM
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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: 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]"?


Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: jj2007 on December 14, 2012, 05:21:45 PM
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 & jmp


On 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
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: japheth on December 15, 2012, 01:21:56 AM
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.
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: jj2007 on December 15, 2012, 01:27:28 AM
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 ;-)
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: dedndave on December 15, 2012, 02:51:15 AM
the difference is that EAX gets destroyed   :P
Title: Re: GENERAL PROTECTION FAULT - Why?
Post by: frktons on December 15, 2012, 04:49:34 AM
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.