Assumptions About Assembly Code

Polyspace® recognizes most inline assemblers as introduction of assembly code. The verification ignores the assembly code but accounts for the fact that the assembly code can modify variables in the C code.

If introduction of assembly code causes compilation errors:

  1. Embed the assembly code between a #pragma my_asm_begin and a #pragma my_asm_end statement.

  2. Specify the analysis option -asm-begin my_asm_begin -asm-end my_asm_end.

For more information, see -asm-begin -asm-end.

Recognized Inline Assemblers

Polyspace recognizes these inline assemblers as introduction of assembly code.

  • asm

    Examples:

    • int f(void)
      {
      	asm ("% reg val; mtmsr val;");
      	asm("\tmove.w #$2700,sr");
      	asm("\ttrap #7");
      	asm(" stw r11,0(r3) ");
      	assert (1); // is green
      	return 1;
      }
      
    • int other_ignored2(void)
      {
      	asm "% reg val; mtmsr val;";
      	asm mtmsr val;
      	assert (1); // is green
      	asm ("px = pm(0,%2); \
      		%0 = px1; \
      		%1 = px2;"
      		: "=d" (data_16), "=d" (data_32)
      		: "y" ((UI_32 pm *)ram_address):
      "px");
      	assert (1); // is green
      }
      
    • int other_ignored4(void)
      {
      	asm {
      		port_in: /* byte = port_in(port); */
      		mov EAX, 0
      		mov EDX, 4[ESP]
      			in AL, DX
      			ret
      			port_out: /* port_out(byte,port); */
      		mov EDX, 8[ESP]
      		mov EAX, 4[ESP]
      		out DX, AL
      		ret }
      assert (1); // is green
      }
      

  • __asm__

    Examples:

    • int other_ignored6(void)
      {
      #define A_MACRO(bus_controller_mode) \
      	__asm__ volatile("nop"); \
      	__asm__ volatile("nop"); \
      	__asm__ volatile("nop"); \
      	__asm__ volatile("nop"); \
      	__asm__ volatile("nop"); \
      	__asm__ volatile("nop")
      		assert (1); // is green
      		A_MACRO(x);
      		assert (1); // is green
      		return 1;
      }
      
    • int other_ignored1(void)
      {
      	__asm
      		{MOV R8,R8
      		MOV R8,R8
      		MOV R8,R8
      		MOV R8,R8
      		MOV R8,R8}
      	assert (1); // is green
      }
      
    • int GNUC_include (void)
      {
      	extern int __P (char *__pattern, int __flags,
      	int (*__errfunc) (char *, int),
      	unsigned *__pglob) __asm__ ("glob64");
      	__asm__ ("rorw $8, %w0" \
      		: "=r" (__v) \
      		: "0" ((guint16) (val)));
      	__asm__ ("st g14,%0" : "=m" (*(AP)));
      	__asm("" \
      		: "=r" (__t.c) \
      		: "0" ((((union { int i, j; } *) (AP))++)->i));
      	assert (1); // is green
      	return (int) 3 __asm__("% reg val");
      }
      
    • int other_ignored3(void)
      {
      	__asm {ldab 0xffff,0;trapdis;};
      __asm {ldab 0xffff,1;trapdis;};
      	assert (1); // is green
      	__asm__ ("% reg val");
      	__asm__ ("mtmsr val");
      	assert (1); // is green
      	return 2;
      }
      

  • #pragma asm #pragma endasm

    Examples:

    • int pragma_ignored(void)
      {
      	#pragma asm
      		SRST
      	#pragma endasm
      		assert (1); // is green
      }
    • void test(void)
      {
        #asm
          mov _as:pe, reg
      	   jre _nop
        #endasm
      	 int r;
      	 r=0;
      	 r++;
      }

Single Function Containing Assembly Code

The software stubs a function that is preceded by asm, even if a body is defined.

asm int h(int tt)              // function h is stubbed even if body is defined
{ 
  % reg val;                   // ignored 
  mtmsr val;                  // ignored 
  return 3;                     // ignored 
}; 

void f(void) { 
  int x; 
  x = h(3);                     // x is full-range 
}

Multiple Functions Containing Assembly Code

The functions that you specify through the following pragma are stubbed automatically, even if function bodies are defined.

#pragma inline_asm(list of functions)

Code examples:

#pragma inline_asm(ex1, ex2) 
   // The functions ex1 and ex2 are 
   // stubbed, even if their bodies are defined 

int ex1(void) 
{ 
  % reg val; 
  mtmsr val; 
  return 3;                       // ignored 
}; 

int ex2(void) 
{ 
  % reg val; 
  mtmsr val; 
  assert (1);                    // ignored 
  return 3; 
}; 


#pragma inline_asm(ex3)  // the definition of ex3 is ignored 

int ex3(void) 
{ 
  % reg val; 
  mtmsr val; 				// ignored 
  return 3; 
}; 

void f(void) { 
  int x; 

  x = ex1();   				// ex1 is stubbed : x is full-range 
  x = ex2();   				// ex2 is stubbed : x is full-range 
  x = ex3();   				// ex3 is stubbed : x is full-range 
}

Local Variables in Functions with Assembly Code

The verification ignores the content of assembly language instructions, but following the instructions, it makes some assumptions about:

  • Uninitialized local variables: The assembly instructions can initialize these variables.

  • Initialized local variables: The assembly instructions can write any possible value to the variables allowed by the variable data types.

For instance, the function f has assembly code introduced through the asm statement.

int f(void) { 
    int val1, val2 = 0; 
    asm("mov 4%0,%%eax"::"m"(val1));
    return (val1 + val2); 
}
On the return statement, the Non-initialized local variable check has the following results:

  • val1: The check is orange because the assembly instruction can initialize val1.

  • val2: The check is green. However, val2 can have any int value.

If the variable is static, the assumptions are true anywhere in the function body, even before the assembly instructions.