inline assembly problem.

Hello.

I am having a VS 2010 debug problem. It seams to think it is wrong to pop things off the stack.

I had to switch to VS 2010 and now am having with problems with inline assembly code.

Some instructions that change the stack pointer are causing an exception. It seams to be any
that pop things off the stack.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//
//	mov	eax,<node>
//	call	_node
//
__declspec(naked) void _node() {_asm {

	push	eax			// push node name string ptr
	mov	eax,sznodeh+szptr	// size of node object
	push	eax
	call	malloc			// allocate a node
	lea	esp,[esp+szinta]	// remove alloc size
	lea	eax,[eax+sznodeh]	// object*
	mov	PtrObjTyp_a,_TYP_node	// Set type
	pop	dword ptr [eax]		// drop in name ptr
	mov	ebx,NodePtr		// puting node on node stack
	lea	ebx,[ebx-szptr]         // adjust stack ptr
	mov	NodePtr,ebx		// ....
	mov	[ebx],eax		// Put node pointer on stack.
	ret
}}


In the above the lea instruction is causing a "0xC0000005: Access violation".

Tried "pop ecx" same problem.

I was using CodeWorrior but it is now having problems on Windows 7. It is getting a random "unknown error" when starting a debug session. But when it does work I do not have any problems with the stack. I can change the esp with an add, lea or a pop.

Is there anyway to disable this exception in VS 2010. Does 2013 have have the same problem?

Is there another debuger that will work on a windows 7 64 bit AMD processor.

Thanks
Last edited on
add another pop instruction.
you must have same amount of PUSHs and POPs to align the stack. (as far as i know)
the RET address is on the stack also, so if you push two values and pop only one, then RET is corrupted.
Last edited on
igor1985 Thanks for the response. But the stack as you are explaining is not the problem.

1
2
3
4
	push	word ptr a1		// pushes a word 2 bytes data
	push	offset a2		// pushes an address 4 bytes
	call	something
	add	esp,6			// adjust stack for 6 bytes pushed 


The code above shows a valid way of removing passed arguments. At least on older versions of windows and using CodeWarrior 8 ide. However CodeWarrior is an old program and I have to keep closing it and reloading and eventually reloading windows to get it to compile and debug. I get a windows pop up system error caused by CodeWarior. Usually when starting a debug. Sometimes when starting a build. With VC2010 when debugging I get a run time error on the stack adjustments.

This is part meta compiler compiler I am implementing. It is basically all assembly code. Not standard c or c++. The functions are naked assembly function like the above. ebp is used to mark a parser backup point. Not the normal uses as a base pointer.

Syntax rules are compiled into machine code not a table. I am hand compiling the compiler into IA86 code. I have been programming sense 1965. Mostly in assembly. I assure you that I know what I am doing with the stack. It is not the standard C usage. This has to do with VC2010 debugger.

The following library routines illustrate stack manipulation. Hopefully the comments are enough explanation:

The success or failure of a match is returned in the zero flag.
call <rule>
je <success>
or
jne <failure>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/************** Set up functions for cc matching function **************\
*									*
*  cc matching function are called by token making and grammer rules to *
*  match strings and characters in the input stream.			*
*									*
*		!! This s assembly code in a C++ wraper !!!!		*
*									*
*  __savePntrs is called on entry by string match function to save the	*
*  input stream state required to Back Track a failed match. The back	*
*  tracking does not have to handle reentricy or stacked states. Objects*
*  are not put on the parse stack or node stack by them. Back Tracking	*
*  is only done when they fail so only the input stream state is saved	*
*  staticly.								*
*									*
*  On success a match function simply returns success. On failure it	*
*  must restore the input stream state. To restore the input stream	*
*  use the folowing:							*
*									*
*	jmp	__rstrPntrs						*
*									*
*  __rstrPntrs is alwayse jumped to on failure by a matching		*
*  function and only restores the input stream state			*
*									*
*  The token skipclass skiping is also affected by matching functions   *
*  When called from a token rule a match will set the partial match	*
*  flag that prevents further skipclass skipping. The flag may only be	*
*  set when a token rule is active.					*
*									*
\***********************************************************************/

__declspec(naked) void __savePntrs(){_asm{  // crazy stack minipulation!!

/***********************************************************************\
* __savePntrs saves input stream state for string match function call: 	*
*									*
*	push	offset <string address>	// string to match		*
*	call	_match_function_	// _CmpStr _KeepStr _NotStr	*
*  <return eq: success ne: failure: i.e. je someware // on success>	*
*									*
*	on entry a match function calls __savePntrs			*
*									*
*__declspec(naked) void _match_function_() {_asm{			*
*	call	__savePntrs						*
*    <return from __savePntrs>						*
*									*
* stack on entry to __savePntrs:					*
* [esp+8]	<string ptr>						*
* [esp+4]	<return from _matching function_>			*
* [esp+0]	<return from __savePntrs> to _matching function_ 	*
*									*
*     rearange stack: Stack on entry as above				*
*									*
*    preserving the calling rule's ecx					*
\***********************************************************************/

	xchg	ecx,[esp+4]     // swap ecx for _matching function_'s return
	xchg	ecx,[esp+8]     // swap return for char* str

/********************* stack is not arranged so: ***********************\
* [esp+8]	<return from _matching function_>			*
* [esp+4]	callers saved ecx					*
* [esp+0]	<return from __savePntrs> to _matching function_ 	*
*   ecx		<string address> pointer				*
*									*
* Stack now as above with ecx *string parameter from [esp+8] on entry	*
*									*
\***********************************************************************/

	mov	strng_parm,ecx		// save string parameter pointer
	mov	ecx,InPutFCB		// point ecx at FCB

<file control block saved, code not shown >

	...

	mov	al,TokenFlg		// save corrent flags state
	mov	token_stats,al		// so can be restored on fail

//  Got TokenFlg skipclass state. Matching can not skip skipclass once any 
//  characters have been matchd. That state is pased back to the matching 
//  function in the zero status flag by the following test instruction.

	mov	eax,FCB_dataptr(ecx)	// 
	movzx	eax,byte ptr [eax]	// get input stream character

	mov	ecx,strng_parm		// point ecx at string parameter
	ret

/***********************************************************************\
*									*
*    Stack on return to match function:					*
*									*
* [esp+4]      origional <return from _matching function_>		*
* [esp+0]      callers saved ecx   <must be poped by functon>		*
*   ecx        points at string to match <string address>		*
*   NOTE.  __rstrPntrs  will restore callers ecx. Do not pop ecx	*
*									*
*   ecx only need be poped on success before a return.			*
*	pop	ecx		// needs restoring			*
*	ret			// before a successful return		*
*									*
* NO POP ECX before:							*
*	jmp	__rstrPntrs	// ecx will be restored by __rstrPntrs 	*
*									*
*    Input stream state saved.						*
\***********************************************************************/
}}

// **************************************************************
// *********  NEVER EVER CALL THIS FUNCTION EVER NEVER  *********
//
__declspec(naked) void __rstrPntrs(){_asm{ // match string reset input stream.

//   !*!*!*!*!*!*!*!*!  COMMON FAIL EXIT CODE  !*!*!*!*!*!*!*!*!
//   !*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
//   !*!*!*!  __rstrPntrs is always jumped to with saved !*!*!*!
//   !*!*!*!  ecx left on the stack to restore on exit.  !*!*!*!
//   !*!*!*!       THIS FUNCTION IS ALWAYS JMPed to      !*!*!*!
//   !*!*!*!      NEVER EVER !! CALLED !!  NEVER EVER    !*!*!*!
//   !*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
//   !*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!


<file control block restored, code not shown data pointer excepted>

	mov	eax,markdataptr		// get daved data pointer
	mov	FCB_dataptr(ecx),eax	// restore to stream pointer

	movzx	eax,byte ptr [ecx]	// eax:curent stream character
	pop	ecx			// ecx of match functions restored
	ret				// return failure. ne condition
}}


Grammar rules are extended bnf parsing tree/list building rules:

1
2
  expr = term $(('+':ADD|'-':SUB) tern!2);
  term = factor $(('*':MPY|'/':DIV) factor!2);

the expresion
a*b+(c/5-d);
trnasforms to
ADD[MPY[a,b],SUB[DIV[c,5],d]]
The tree processing language:
1
2
3
4
5
6
7
arith(ADD[arith(x),arith(y)])=> <add x,y;>;
arith(SUB[arith(x),arith(y)])=> <sub x,y;>;
arith(MPY[arith(x),arith(y)])=> <mpy x,y;>;
arith(DIV[arith(x),arith(y)])=> <div x,y;>;

arith(x)=> %r1=asignreg()=>	%r1=assignreg();
				<loadreg %r1,x>;


Sorry if I made this sound like a coding problem.
Registered users can post here. Sign in or register to post.