Specifying and using the list form of a macro

When you specify and use the list form of a macro, you can code for reentrancy by embedding assembly statements that:

  1. Allocate space on the stack (that is, use a local variable). See Figure 2.
  2. Copy the parameter field values from the list form to this allocated space.
  3. Invoke the execute form of the macro that will use the allocated space.
Note: The code format string in Figure 3 invokes the WTO macro by using the execute form of the macro with a user-defined buffer. That example does allow for reentrancy.

You should not have direct reference to symbols within your code format string as the addressability is not guaranteed. The proper way to use the macro is shown in Figure 2, in which all __asm statements are connected through the C variable operands listmsg1 and buff.

Figure 1 provides an example that uses the list form of a macro without considering reentrancy.

Figure 1. Specifying and using the WTO macro (no reentrancy)
      1               2                  3 
   __asm(" WTO 'hello world',MF=L" : "DS"(listmsg1));    

   int main() { 
           4                                    5 
         __asm( " WTO  MF=(E,(%0)) " : : "r"(&listmsg1));    
         return 0;  
   } 
Notes:
  1. The first __asm statement invokes the macro WTO in the list form (MF=L). In order for the list form of the macro to be invoked with the values of the parameter fields defined, the __asm statement must be specified in the global scope.
  2. The message text "hello world" is provided as a macro parameter.
  3. The “DS” constraint indicates that this is a data definition, with the name of the C variable defined as the variable listmsg1. Because listmsg1 is implicitly defined as a structure, it can be referenced in subsequent __asm statements, therefore the “DS” constraint must be specified in the output operand list. By default, the compiler allocates 256 bytes of memory for the variable listmsg1, which should satisfy most requirements. You can change the memory allocation size (for example, "DS:100"(listmsg1) to allocate 100 bytes). You can allocate more than 256 bytes of space.
  4. The second __asm statement invokes the macro WTO in the execute form (MF=(E,(%0)). It takes the address of the storage defined in the list form.
  5. The address of the variable listmsg1 is defined as an input operand that is stored in a register.

Support of reentrancy requirements

If the execute form of the macro needs to change the fields provided in the list form, the assembly statements embedded by the __asm statement in Figure 1 will be incorrect when support for reentrancy is required. The proper way to use the macro is shown in Figure 2.

Figure 2. Support for reentrancy in a code format string
   __asm(" WTO 'hello world',MF=L" : "DS"(listmsg1));  1 

   int main() {
      __asm(" WTO 'hello world',MF=L" : "DS”(buff));   2 
      buff = listmsg1;                                 3 

      __asm( " WTO  MF=(E,(%0)) " : : "r"(&buff));
      return 0;  
   } 
Notes:
  1. The first __asm statement uses the list form of the macro WTO to define the variable listmsg1.
  2. The second __asm statement, specified within function scope with a “DS” constraint, will allocate stack space for the variable buff but will not actually initialize the parameter values.
  3. The size of this variable should match that of the corresponding __asm statement in global scope. An assignment copies the actual parameter values from the list form to this buffer.