ED Instruction and Edit Masks



High Level Assembler(HLASM) for MVS & VM & VSE

ED Instruction and Edit Masks

Postby steve-myers » Sat Aug 10, 2013 12:38 am

The following program actually works. The web site will not display the program correctly in the code block. Internet Explorer appears to do better than Firefox or Chrome, but better is a matter of degree. You might click on the Quote block, and copy the program to a Notepad window if your workstation is running Windows. or something similar if your workstation is running Linux. I'm hopeful someone will attempt to answer some of the questions. One of the questions requires some knowledge of the internals of how MVS operates and is probably beyond the scope of knowledge of most of the people in this forum, but I can hope. In a few days I will post the answers.
EDITTIME CSECT                     Define program CSECT
         USING *,12                Establish program addressability
         SAVE  (14,12),,'EDITTIME &SYSDATE &SYSTIME'  Save registers
         LR    12,15               Copy entry point address to reg 12
         LA    2,10                Set reg 2 = 10
LOOP     TIME  DEC                 Get date and time
         STM   0,1,SAVETIME        Save time of day
         UNPK  SAVEWD1(9),SAVETIME(5)   Convert
         UNPK  SAVEWD2(9),SAVETIME+4(5)  SAVETIME
         TR    SAVEWD1,HEXTAB             to
         TR    SAVEWD2,HEXTAB              hexadecimal
         MVI   SAVEWD1+L'SAVEWD1,C' '       digits
         LA    0,L'LISTSAVE        Write translated SAVETIME
         LA    1,LISTSAVE           to the TSO terminal
         TPUT  (1),(0),R
         AP    SAVETIME(8),=P'1900000'  Convert 0cyy in p'0cyyddd'    ->
                                         to a proper year
         MVC   TIMEOFDAY,EDITMASK  Init TIMEOFDAY data area
         ED    TIMEOFDAY,SAVETIME  Translate packed decimal digits to ->
                                    numeric characters
         LA    0,L'TIMEOFDAY-1     Load length of data area
         LA    1,TIMEOFDAY+1       Load address of data area
         TPUT  (1),(0),R           Write data area to the TSO terminal
         MVI   ECB,0               Reset the completion ECB
         STIMER REAL,ITIMEUP,BINTVL==F'100'  Start the timer interval
         WAIT  1,ECB=ECB           Wait for the time interval to      ->
                                    complete
         BCT   2,LOOP              Do it again
         RETURN (14,12),T,RC=0     Restore registers
         DROP  ,
* STIMER timer completion exit
         CNOP  0,8
         USING *,2                 Establish ITIMEUP addressability
ITIMEUP  LR    2,15                Copy entry point address to reg 2
         LR    3,14                Copy return address to reg 3
         POST  ECB,0               Post the ECB
         BR    3                   Return to STIMER
SAVETIME DC    2F'0'
ECB      DC    F'0'
EDITMASK DC    0C' HH:MM:DD:HH YYYY/DDD'
         DC    C' ',X'2120',C':',X'2020',C':',X'2020',C'.',X'2020'
         DC    C' ',X'20202020',C'/',X'202020'
LISTSAVE DC    0C'HHHHHHHH HHHHHHHH'
SAVEWD1  DC    C'HHHHHHHH',C' '
SAVEWD2  DC    C'HHHHHHHH',C' '
TIMEOFDAY DC   CL(L'EDITMASK)' ',0D'0'
         LTORG ,                   Insert the literal pool here
         ORG   EDITTIME+C'0'
         ORG   ,
         DC    0D'0'
HEXTAB   EQU   *-C'0'
         DC    C'0123456789ABCDEF'
         END   EDITTIME
  1. Why does AP SAVETIME(8),=P'1900000' work?
  2. What is the purpose of the following code?
             ORG   EDITTIME+C'0'
             ORG   ,
  3. Why do this complicated business with STIMER and WAIT when STIMER WAIT is much simpler?
  4. If you understand the answer to the first question, this one is real easy: why does the edit mask work?
  5. The "main" program does not obtain a new save area, yet the contents of the original save area are not damaged. Why does the system work this way?
  6. This one is the hardest. This code looks like a subroutine. It is clearly destroying registers 2 and 3 before it returns, but it runs correctly. Why?
             USING *,2
    ITIMEUP  LR    2,15
             LR    3,14
             POST  ECB,0
             BR    3
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: ED Instruction and Edit Masks

Postby Mickeydusaor » Sat Aug 10, 2013 2:44 am

at a quick glance at the ORG EDITTIME+C'0' it looks like it is putting a leading 0 in the &sysdate field
dc   CL8'EDITTIME'
DC  CL8'  08/09/1'
DC  CL7'3 14.02'

will look at the rest on Monday
User avatar
Mickeydusaor
 
Posts: 29
Joined: Fri Feb 24, 2012 11:24 pm
Has thanked: 1 time
Been thanked: 0 time

Re: ED Instruction and Edit Masks

Postby steve-myers » Sat Aug 10, 2013 5:16 am

Mickeydusaor wrote:at a quick glance at the ORG EDITTIME+C'0' it looks like it is putting a leading 0 in the &sysdate field...
No. Not even close.
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: ED Instruction and Edit Masks

Postby steve-myers » Sat Aug 10, 2013 7:27 pm

I'll expand on Mickeydusaor's response.

Let's expand the problem a bit:
EDITTIME CSECT
         USING *,12
         ...
         UNPK  OUTPUT(3),DATA(2)
         TR    OUTPUT,HEXTAB
         ...
DATA     DC    X'0C',X'00'
OUTPUT   DC    C'00',X'00'
         ...
         ORG   EDITTIME+C'0'
         ORG   ,
HEXTAB   EQU   *-C'0'
         DC    C'0123456789ABCDEF'
After the UNPK instruction executes the data in OUTPUT is X'F0FC' . Read the description of the UNPK instruction very carefully to understand why this is so.

ORG EDITTIME+C'0'

C'0' has a value. The hexadecimal value for C'0' is F0, or 240 decimal. The purpose of the ORG Assembler instruction is to reset the value of the location counter, so after the Assembler processes the ORG instruction, the location counter is at EDITTIME+C'0' or EDITTIME+240. An ORG instruction with no operands sets the value of the location counter to the highest point it has encountered so far. From the actual Assembler listing of EDITTIME:
000108                00108 000F0    87          ORG   EDITTIME+C'0'
0000F0                000F0 00108    88          ORG   ,
The first line tells me the actual value of the location counter was 000108 before the ORG instruction was processed by the Assembler, and it will be reset to 000F0.

The second line tells me the location counter value is 0000F0, and the ORG instruction will reset it to 00108.

Now EDITTIME is a very small program. What will the Assembler do if the location counter value when ORG EDITTIME+C'0' was processed by the Assembler was less than 0000F0? It will set the location counter to 0000F0. After the second ORG is processed by the Assembler, since the highest value of the location counter was 0000F0, is will still be 0000F0. Why go through these gyrations? Again, going back to the listing:
                      00018          90 HEXTAB   EQU   *-C'0'
000108 F0F1F2F3F4F5F6F7              91  DC C'0123456789ABCDEF'
The first line tells me the assigned location value for HEXTAB is 00018. I compressed the second line a little so it would display better in the code box. Now lets's go back to the listing.
00003C DC07 C0D9 C018 000D9 00018    21  TR SAVEWD1,HEXTAB
The location counter is 00003C. DC07 C0D9 C018 is the hexadecimal representation of the instruction; C018 is the hexadecimal representation of the base/displacement address of HEXTAB: the machine will add 018 to the contents of register C. There are good things about this system, but the "displacement" value must be 0 or positive. It cannot be negative. The reason to go through the gyrations with ORG Assembler instructions ensures the displacement value for HEXTAB will be valid. If the module is very small, what will be in storage before HEXTAB at location counter 0000F0? It will not be defined, so anything can be there.
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: ED Instruction and Edit Masks

Postby steve-myers » Tue Aug 13, 2013 11:26 am

I won't repeat the questions here.

1) The TIME DEC macro returns 8 packed decimal digits in register 0, and 7 packed decimal digits and a packed decimal sign. After it stores the 2 registers in SAVETIME, SAVETIME is the equivalent of an 8 byte packed decimal data area. The low order 7 packed decimal digits have the form 0cyyddd. c is the century, 1 for 2000, and 0 for 1900. Byr adding 1900 to cyy we get a "true year." This year cyy is returning 113; 1900+113 = 2013.

2) Already discussed.

3) For a job run in batch, it doesn't make any difference. When STIMER WAIT is run in a TSO session, an attempt to get an attention through to the TSO session is deferred until thewait time completes. For this code, where the wait time is 1 second it really doesn't matter. For longer interval it can by annoying.

4) The SAVETIME data area is the equivalent of 15 packed decimal digits. The edit mask specifies 15 digit select characters, so the final result is hh:mm:ss.hh yyyy/ddd. The first h will be blank if the program is run before 10 AM.

5) You need a new save area if your program calls a sbroutine or it does I/O using the GET/PUT/READ/WRITE/CHECK macros. The TIME, STIMER, WAIT and TPUT macros all SVC instructions to invoke system services; the SVC interrupt handler (yes, the SVC instruction generates an interrupt) saves your registers elsewhere, and restores them when the SVC service completes.

6) The code is sort of a subroutine. Logically, it is called by the operating system. The trouble is if it really worked the way I just described, your little subroutine would be entered as though it were the operating system. That's a no no; it would be an open sesame to all sorts of mischief. So what really happens is trickery.

Essentially all programs in MVS run under control of a system control block called a request block. There are oodles and oodles of request block types. Most programs run under a "Program Request Block," which makes sense. One of the fields in the request block is a "wait count" field, which is just the number of event control blocks that must be marked complete. If the wait count field is not 0, the system will not run your program. In order to run the little subroutine, timer services executes a macro called CIRB, which creates a special type of request block called an IRB (Interrupt Request Block) when the timer interval completes and sets it tun run your routine. Once the CIRB macro completes, timer services is done and the operating system looks for other work, like run other tasks. Sooner or later it will get to your task, it will notice there is a request block (the IRB) with a wait count = 0, and it will start your interrupt program. The POST macro in the interrupt program will, among other tasks, will locate the request block that the event control block is associated with and reduce its wait count by 1. Now, register 14, when the interrupt routine is entered, does not really point to anything in the operating system; it actually points to an SVC 3 instruction, which starts system code to terminate a request block. If the request block is the last request block for the task, which this should not be, it will terminate the task.

These users thanked the author steve-myers for the post:
Peter_Mann (Fri Aug 16, 2013 2:47 am)
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: ED Instruction and Edit Masks

Postby bobguo » Thu Aug 15, 2013 7:49 pm

00003C DC07 C0D9 C018 000D9 00018    21  TR SAVEWD1,HEXTAB


so hard to understand this program.

C018 should be the address of HEXTAB, but obviously, (R12)+018 points to another address, can you explain it? thanks.
bobguo
 
Posts: 76
Joined: Thu Apr 26, 2012 11:18 am
Location: shanghai
Has thanked: 22 times
Been thanked: 0 time

Re: ED Instruction and Edit Masks

Postby bobguo » Thu Aug 15, 2013 8:03 pm

0000E8                000E8 000F0    82          ORG   EDITTIME+C'0'     
0000F0                000F0 000F0    83          ORG   ,                 
0000F0                               84          DC    0D'0'             
                      00000          85 HEXTAB   EQU   *-C'0'             
0000F0 F0F1F2F3F4F5F6F7              86          DC    C'0123456789ABCDEF'
000000                               87          END   EDITTIME     


here, HEXTAB EQU *-C'0' = HEXTAB EQU 0?

and i think HEXTAB EQU 0 is similar to "R0 EQU 0", both of them don't have address, they are just one value 0, is it right?
bobguo
 
Posts: 76
Joined: Thu Apr 26, 2012 11:18 am
Location: shanghai
Has thanked: 22 times
Been thanked: 0 time

Re: ED Instruction and Edit Masks

Postby steve-myers » Thu Aug 15, 2013 9:32 pm

Yes and no.

HEXTAB DC C'0123456789ABCDEF'

Regardless of the "value," HEXTAB is a relocatable value. This means several things
  1. When it is used in an address constant, e.g., DC A(HEXTAB) when the program is loaded into storage, the data stored in the 4 bytes will be the address of of the storage assigned to the symbol.
  2. When HEXTAB is used in an instruction, provided it is in storage covered by a USING Assembler instruction, the Assembler will compute the "displacement" and base register from the USING, and store them in the binary instruction.
*, in IBM Assemblers, always means the current value of the location counter. That means it is relocatable. So, *-C'0' is relocatable because C'0' is a constant.

HEXTAB-C'0' is relocatable provided HEXTAB is relocatable.

You can do other types of arithmetic on relocatable values, provided they are in the same logical domain.

TABLE DC 256AL1(*-TABLE)

IBM assemblers will generate 256 1 byte data areas containing 1 2 3 4 5 6 7 8 9 ... 255.

I have to go now.
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: ED Instruction and Edit Masks

Postby steve-myers » Thu Aug 15, 2013 11:22 pm

This table is in most of my programs that write a SYSPRINT type data set. What is its purpose?
OELINES  DC    0XL256'0'                                 
* THESE STATEMENTS DEPEND ON THE EBCDIC COLLATING SEQUENCE
         DC    (C' ')X'FF',AL1(1) BLANK < + < - < 0       
         DC    (C'+'-(*-OELINES))X'FF',AL1(0)             
         DC    (C'-'-(*-OELINES))X'FF',AL1(3)             
         DC    (C'0'-(*-OELINES))X'FF',AL1(2)             
         DC    (256-(*-OELINES))X'FF'

Hint, though it's not much of a hint, an argument can be made that the AL1(2) in (C'0'-(*-OELINES))X'FF',AL1(2) should be AL1(2,255). Why?

If you can figure this out - and it's not easy - you will have a very solid idea about how arithmetic with relocatable values works in Assembler.
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: ED Instruction and Edit Masks

Postby bobguo » Mon Aug 19, 2013 9:13 am

OELINES  DC    0XL256'0'                                 
* THESE STATEMENTS DEPEND ON THE EBCDIC COLLATING SEQUENCE
         DC    (C' ')X'FF',AL1(1) BLANK < + < - < 0       
         DC    (C'+'-(*-OELINES))X'FF',AL1(0)             
         DC    (C'-'-(*-OELINES))X'FF',AL1(3)             
         DC    (C'0'-(*-OELINES))X'FF',AL1(2)             
         DC    (256-(*-OELINES))X'FF'


AL1(2) = AL1(2,255) = AL1(2,255,255) = AL1(2,255,255,255), we add one 255 more, the value of * should be +1, so the table above should equal to:

OELINES  DC    0XL256'0'                                 
         DC    (C' ')X'FF',AL1(1) BLANK < + < - < 0       
         DC    (C'+'-(*-OELINES))X'FF',AL1(0,255)             
         DC    (C'-'-(*-OELINES))X'FF',AL1(3,255,255)             
         DC    (C'0'-(*-OELINES))X'FF',AL1(2,255,255,255)             
         DC    (256-(*-OELINES))X'FF'


right?
bobguo
 
Posts: 76
Joined: Thu Apr 26, 2012 11:18 am
Location: shanghai
Has thanked: 22 times
Been thanked: 0 time

Next

Return to Assembler

 


  • Related topics
    Replies
    Views
    Last post