When you specify and use the list form of a macro, you can code
for reentrancy by embedding assembly statements that:
- Allocate space on the stack (that is, use a local variable). See Figure 2.
- Copy the parameter field values from the list form to this allocated
space.
- 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: - 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.
- The message text "hello world" is provided as a macro
parameter.
- 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.
- 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.
- 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: - The first __asm statement uses the list form
of the macro WTO to define the variable listmsg1.
- 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.
- 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.