Language Assembler (DEC VAX)
Date: | 04/20/05 |
Author: | Anonymous |
URL: | n/a |
Comments: | 2 |
Info: | n/a |
Score: | (3.03 in 36 votes) |
.TITLE Beers 99 Bottles of Beer on the Wall ;++ ; This program will produce the output for the song "99 Bottles of Beer" ; and display it to the logical device SYS$OUTPUT. VMS makes this ; simple due to its wealth of library routines. ; ; Thrilling, isn't it? ; ; This presumes a VAX processor, and the VMS operating system (VAX/VMS ; or OpenVMS). Novices are encouraged to reference the following: ; ; VAX Macro and Instruction Set Reference Manual ; VMS System Services Reference Manual ; VMS Run-Time Library (LIB$) Manual ; ; Author : David A. Seagle ; Date : 02-Jul-2003 ;-- ; ; Define symbols, constants, etc. used in this module. ; MAX_SIZE = 128 ; max text buffer length in bytes TOTAL_BEERS = 99 ; how many beers to consume ; ; Define templates for the various output lines. Note that we must ; use ASCII string descriptors since that is what the library routines ; (and the system services they call) expect. Also, we embed control ; strings for use by the $FAO system service within these templates, ; and substitute values for them during the run. ; NUM_BEERS: .ASCID '!SL bottle!%S of beer on the wall!/'- '!SL bottle!%S of beer' THE_BRIDGE: .ASCID 'Take one down, and pass it around!/'- '!SL bottle!%S of beer on the wall!/' NO_MORE: .ASCID 'Take it down, and pass it around!/'- 'Then go to the store and buy us some more' ; ; Set up a text buffer for use as an output line. Also, set up the ; string descriptor to describe this buffer. We are "rolling our own" ; here for convenience because we do not have a static text buffer ; value as we did with the output templates. This also makes it more ; obvious where the descriptor length is located since we plan to ; manipulate it during the run. ; OUT_BUFFER: .BLKB MAX_SIZE ; output buffer/line OUT_DESC: .WORD MAX_SIZE ; output buffer length in bytes .BYTE DSC$K_DTYPE_T ; code for "use string data type" .BYTE DSC$K_CLASS_S ; code for "use fixed descriptor" .ADDRESS OUT_BUFFER ; pointer to the output text buffer ; ; Allocate a longword to store any failure status value we might see ; ERROR_CODE: .BLKL 1 ; last error code encountered ;****************************** ;* Entry Point for Program!!! * ;****************************** .ENTRY BEERS,^M<R7> ; entry point, save R7 automatically ; ; Initialize. ; START: MOVL #TOTAL_BEERS, R7 ; initialize beer counter (use R7) MOVL #SS$_NORMAL, ERROR_CODE ; initialize error code to normal BRB DISPLAY_COUNT ; start by displaying the count ; ; Output the bridge text using the current value of the beer counter. ; ; Remember that the library routines expect their parameters in the order ; given in the documentation for their formal parameters, and will read ; them as offsets from the stack pointer. So, we must push these actuals ; onto the stack in reverse order to accommodate. ; ; Keep in mind that we have set things up such that calls to the $FAO ; system service will write the length of the text buffer it constructed ; back into the output buffer's descriptor. This requires us to reset the ; descriptor before each call. If we do not, $FAO might return an error ; indicating that the buffer is too small for its output result based upon ; a stale length in the descriptor. ; DISPLAY_BRIDGE: MOVW #MAX_SIZE, OUT_DESC ; reset buffer length to maximum PUSHL R7 ; count of the beer we are consuming PUSHAQ OUT_DESC ; address of output buffer descriptor PUSHAW OUT_DESC ; final formatted buffer length PUSHAQ THE_BRIDGE ; input template descriptor CALLS #4, G^LIB$SYS_FAO ; create formatted ASCII output buffer CMPL R0, #SS$_NORMAL ; ensure $FAO was successful BNEQ FAILURE_EXIT ; branch to failure exit if not PUSHAQ OUT_DESC ; address of output line descriptor CALLS #1, G^LIB$PUT_OUTPUT ; display output buffer on SYS$OUTPUT ; ; Output the current beer text to SYS$OUTPUT. Each $FAO template has ; substitution placeholders embedded, so remember to load those runtime ; values (in reverse order) onto the stack as well. ; DISPLAY_COUNT: MOVW #MAX_SIZE, OUT_DESC ; reset buffer length to maximum PUSHL R7 ; second substitution value to use PUSHL R7 ; first substitution value to use PUSHAQ OUT_DESC ; address of output buffer descriptor PUSHAW OUT_DESC ; final formatted buffer length PUSHAQ NUM_BEERS ; input template descriptor CALLS #5, G^LIB$SYS_FAO ; create formatted ASCII output buffer CMPL R0, #SS$_NORMAL ; ensure $FAO was successful BNEQ FAILURE_EXIT ; branch to failure exit if not PUSHAQ OUT_DESC ; address of output line descriptor CALLS #1, G^LIB$PUT_OUTPUT ; display output buffer on SYS$OUTPUT SOBGTR R7, DISPLAY_BRIDGE ; consume a beer, continue if non-zero ; ; If our beer counter is not greater than zero, output the final tag line ; to SYS$OUTPUT before we exit. ; DISPLAY_FINAL: MOVW #MAX_SIZE, OUT_DESC ; reset buffer length to maximum PUSHAQ OUT_DESC ; address of output buffer descriptor PUSHAW OUT_DESC ; final formatted buffer length PUSHAQ NO_MORE ; input string template descriptor CALLS #3, G^LIB$SYS_FAO ; create formatted ASCII output buffer CMPL R0, #SS$_NORMAL ; ensure $FAO was successful BNEQ FAILURE_EXIT ; branch to failure exit if not PUSHAQ OUT_DESC ; address of output line descriptor CALLS #1, G^LIB$PUT_OUTPUT ; display output buffer on SYS$OUTPUT MOVL #SS$_NORMAL, ERROR_CODE ; set error code to normal BRB COMMON_EXIT ; exit with normal completion status ; ; Generic error handler which converts the error code into a text message ; equivalent, and displays it to SYS$OUTPUT prior to terminating the image ; with the last error code we encountered. ; FAILURE_EXIT: MOVL R0, ERROR_CODE ; save error code for use in $EXIT MOVW #MAX_SIZE, OUT_DESC ; reset buffer length to maximum PUSHAQ OUT_DESC ; address of output buffer descriptor PUSHAW OUT_DESC ; final formatted buffer length PUSHAL ERROR_CODE ; error code to translate CALLS #3, G^LIB$SYS_GETMSG ; create text message from error code PUSHAQ OUT_DESC ; address of output line descriptor CALLS #1, G^LIB$PUT_OUTPUT ; display output buffer on SYS$OUTPUT COMMON_EXIT: $EXIT_S ERROR_CODE ; exit with our error status .END BEERS
Download Source | Write Comment
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments
Bar Ilan said on 12/08/05 13:17:43
Muskat would have reduce points for bad indentation
John Morrison said on 10/31/06 20:56:52
The "correct" test for an error should be of the form:
BLBC R0,FAILURE_EXIT ; Quit on error - even status return
because successes all have odd error returns. This is true for _everything_ under VMS - not just LIB$SYS_FAO ... so a moderately severe point reduction for this piece of code! (Also, I would have used the "raw" system service, not the LIB$-packaged form - because I'm like that.)
John
PS Bad indentation? As long as DEC-standard tabs don't work, surely, you're being harsh. (I found out the hard way.)