;++ ; MACRO64$HELLO.M64 ; ; © Digital Equipment Corporation 1992, 1993. All rights reserved. ; ; Restricted Rights: Use, duplication, or disclosure by the ; U.S. Government is subject to restrictions as set forth in ; subparagraph (c) (1) (ii) of DFARS 252.227-7013, or in ; FAR 52.227-19, or in FAR 52.227-14 Alt. III, as applicable. ; ; This software is proprietary to and embodies the confidential ; technology of Digital Equipment Corporation. Possession, use, or ; copying of this software and media is authorized only pursuant to ; a valid written license from Digital or an authorized sublicensor. ; ; This is a complete MACRO-64 program which uses the calling-standard macros ; in MACRO64.MLB. This example is one of three installed with MACRO-64: ; ; MACRO64$HELLO.M64 - Simple Hello World program (this program) ; Demonstrates calling standard macros ; MACRO64$WHAMI.M64 - Program that displays WHAMI IPR ; Demonstrates system calls ; MACRO64$PI.M64 - Program that computes PI ; Demonstrates general programming with ; MACRO-64 along with optimization techniques ; ; Digital suggests you become familiar with the concepts illustrated in ; this simple example before you attempt to understand the ; MACRO64$WHAMI.M64 example or the MACRO64$PI.M64 example. ; ; ; This program calls the DEC C Runtime Library routine, printf, to print ; out the following: ; ; © Digital Equipment Corporation 1992, 1993. All rights reserved. ; Hello world, from Nashua, New Hampshire, USA! ; ; The DEC C Runtime library is available with the OpenVMS AXP (TM) Operating ; System, regardless of whether you have purchased and installed the DEC C ; compiler product. ; ; To run this program on OpenVMS AXP (TM), use the following commands: ; ; $ macro/alpha_axp/object=hello sys$examples:macro64$hello ; $ link hello ; $ run hello ;-- ;++ ; The $ROUTINE macro invocation below defines a routine named HELLO. HELLO ; is a stack frame procedure that maintains its caller's context on ; the SP stack. It saves and restores R2 in addition to the frame pointer ; register (FP, or R29). Since we do not specify the stack size, $ROUTINE ; computes the minimum size necessary given the values for the other ; arguments we've specified or defaulted. The $ROUTINE macro defines a ; linkage-section psect and code-section psect. By default, these are ; $LINK$ and $CODE$, respectively, and we will use the defaults. The ; $ROUTINE macro also defines the procedure descriptor for HELLO within ; the linkage section. By default, $ROUTINE generates a standard instruction ; prologue sequence that saves the specified or defaulted registers (in ; this case R2 & FP) and performs the required stack-frame management. The ; $ROUTINE macro leaves you in the code section when it is done. ;-- $routine HELLO, kind=stack, saved_regs=r2 ;++ ; The $LINAKGE_SECTION macro invocation below switches to the linkage-section ; psect of the current routine, HELLO. ;-- $linkage_section ;++ ; The following are the strings to be passed to printf. ;-- COPYRIGHT_MSG: .asciz - ; \xA9 is '©', \x0A is , or '\n' in C parlance "\xA9 Digital Equipment Corporation 1992, 1993. All rights reserved.\x0A" HELLO_MSG: .asciz "Hello world, from %s!\x0A" NASHUA_MSG: .asciz "Nashua, New Hampshire, USA" ;++ ; The $CODE_SECTION macro invocation below switches to the code section ; psect of the current routine, HELLO. Note that since we did not ; specify STANDARD_PROLOGUE=FALSE with the invocation of $ROUTINE to ; suppress generation of a standard prologue instruction sequence, ; $ROUTINE has already generated a standard instruction prologue ; sequence for us. ;-- $code_section ;++ ; We currently have a pointer to our own linkage section in R27. ; However, the first call that we make will destroy that pointer, so we'll ; make a copy of the pointer into R2. ;- mov r27, r2 ;++ ; The $ROUTINE macro call above defined a symbol, $LS, which points to the ; base of the linkage section. We can use this with the .BASE directive to ; simplify our source code for accessing data in the linkage section. ; The following .BASE directive informs the assembler that R2 contains ; the address $LS. With that information, the assembler can then know ; which base register and absolute offset to use when you supply an address ; expression in place of a base register and absolute offset in your ; instruction statements. ;-- .base r2, $LS ;++ ; Perform two calls to DECC$GPRINTF with the $CALL macro. ; The $CALL macro does the following: ; o allocates stack for arguments if needed (in this case, none is ; needed) ; o loads specified arguments into registers or onto the stack, as ; appropriate ; o sets the argument information register, R25 ; o stores a linkage pair for DECC$GPRINTF in HELLO's linkage section ; o loads R26 with the code address of DECC$GPRINTF ; o loads R27 with the address of DECC$GPRINTF's procedure descriptor ; o performs the routine call with a JSR instruction ; o releases argument stack area if any and if the caller doesn't ; return a value on the stack (STACK_RETURN_VALUE=FALSE, which ; is the default) ; ; Note that access to HELLO's linkage section is achieved relative to ; R2 by virtue of the .BASE directive above. ;-- $call DECC$GPRINTF, args=COPYRIGHT_MSG/A $call DECC$GPRINTF, args= ;++ ; Now we'll set the routine return value to normal, successful completion. ;-- MOV #1, R0 ;++ ; Now we can return from HELLO to the operating system. The $RETURN ; macro generates a standard instruction epilogue sequence that restores ; any saved registers and performs the necessary stack-frame management. ;-- $return ;++ ; We must mark the end of each routine with the $END_ROUTINE macro. ;-- $end_routine HELLO ;++ ; The .END directive takes an optional argument which is used as the ; program entry point. If specified, the argument must be the name of a ; global procedure descriptor that is defined within the module. The ; $ROUTINE macro defined the procedure descriptor for HELLO, so we can ; specify HELLO here to make HELLO be the entry point of our program. ;-- .end HELLO