IBM Z and LinuxONE - Languages

Languages

Languages

Broad range of supported development languages and tools allows to transform software delivery practices.

 View Only

Defining storage using inline asm in Metal C for use in system macros

By FANG LU posted Tue March 24, 2020 07:40 PM

  

The Metal C option generates code which does not require support from the Language Environment at runtime. As a result, it must obtain the system services that it needs by calling assembler services directly. This can be done either through callable services or macros. In this blog, I will discuss how to call system macros using inline asm as well as how to define storage for variables used in these system macros.

 

The system macro I will be using as example in this blog will be the WTO (Write to operator) macro. This macro allows you to write messages to one or more operator consoles.

 

As review, recall that macros come in three different forms: standard, list, and execute. In general, the standard form is non-reentrant, making it unsafe for use with system macros. As a result, we will be focusing on the list and execute forms of the WTO macro. The list form of the macro is used to define an area of storage, which the execute form of the macro uses to store the parameters.

 

Example 1:                  

__asm(" WTO 'hello world',MF=L" : "DS"(listmsg1));      (1)

int main() {

 __asm( " WTO MF=(E,(%0)) " : : "r"(&listmsg1));       (2)

 return 0;

}

 

(1): This is the list form of the macro WTO due to “MF=L”. We are also defining the variable listmsg1 here.

(2): This is the execute form of the macro WTO due to “MF=(E,(%0))”. %0 refers to the first argument in the asm instruction which is &listmsg1.

 

Since the list form of the macro defines listmsg1, it becomes a variable that can be used in C outside of inline asm.

 

Example 2:

__asm(" WTO 'hello world',MF=L" : "DS"(listmsg1));

int main() {

 __asm(" WTO ,MF=L" : "DS"(buff));                     (1)

 buff = listmsg1;                                      (2)

 __asm( " WTO MF=(E,(%0)) " : : "r"(&buff));          (3)

 return 0;

}

 

(1): Defining buff similarly to listmsg1.

(2): Copying listmsg1 to buff.

(3): Using buff as the parameter to WTO.

 

However, it is difficult to use the variable defined using the list form in other ways since it is of type “struct __ASM_DS_256” which cannot be easily manipulated in C.

 

As an aside, “DS” by default allocates 256 bytes of space. However, this value can be modified by using “DS:100”(listmsg1) to allocate 100 bytes. Also, “DS:100” will defined a "struct __ASM_DS_100" type.

 

An interesting advantage of using the execute form of the WTO macro is the ability to generate the input parameter using C semantics and syntax. This can be done with any macros as long as the user is aware of the expected format of the macro parameters.

 

Example 3:

struct WTO_PARM                                        (1)

{

    unsigned short len;

    unsigned short code;

    char text[252];

};

 

union WTO_UNION                                       (2)

{                                  

 struct WTO_PARM buff2;

 struct __ASM_DS_256 buff;

};

 

__asm(" WTO 'hello world',MF=L" : "DS"(listmsg1));

int main() {

 union WTO_UNION wto_buff;

 wto_buff.buff = listmsg1;

 wto_buff.buff2.text[1] = 'a';                         (3)

 __asm( " WTO MF=(E,(%0)) " : : "r"(&wto_buff.buff));

 return 0;

}

 

(1): This is the expected format of the parameter for the WTO macro.

(2): Union of "struct __ASM_DS_256" with "struct WTO_PARM" makes it easier for the programmer to access and modify its contents.

(3): The final output is changed from “hello world” to “hallo world”.

 

In this blog, I demonstrated how storage can be defined using the list form of system macros through inline ASM and Metal C as well as how to manipulate the defined storage through C semantics and syntax.

0 comments
0 views

Permalink