IBM Mainframe Assembler

General Articles on Programming in Assembler

The following is a list of links to articles covering a variety of topics in IBM z/OS Assembly language.

  1. Conversion of Binary, Decimal, and Hexadecimal Data
  2. System/z Architecture
  3. Character Data
  4. Packed Decimal Data
  5. Binary Data
  6. The Define Constant Directive
  7. Data Conversions
  8. Organizing a Simple Assembler Program
  9. Sequential File Processing (QSAM Files)
  10. Loops
  11. Packed Decimal Arithmetic
  12. Base Displacement Addressing
  13. Dsects
  14. Explicit Addressing
  15. Instruction Formats
  16. Program Linkage
  17. Address Constants
  18. Reading Object Code
  19. Base Displacement Addressing
  20. Explicit Addressing
  21. Jumping Into Branches
  22. Techniques For Converting From Binary to Packed-decimal

A Video Course For IBM Assembler Language

Watch the videos … learn to program in assembler.

  1. Assembler Course PowerPoints
  2. Starting Assembler 1
  3. Starting Assembler 2
  4. MVI, DCB, Open, Close, Put, Get, Standard Entry and Exit
  5. A First Program
  6. A First Program (.zip)
  7. Removing Assembly Errors in the First Program
  8. Pack Instruction Video
  9. Pack Instruction PPT
  10. UNPK Instruction Video
  11. UNPK Instruction PPT
  12. ED Instruction Video
  13. ED Instruction PPT
  14. LA Instruction Video
  15. LA Instruction PPT
  16. L Instruction Video
  17. L Instruction PPT
  18. Loading Multiple Registers Video
  19. Loading Multiple Registers PPT
  20. The Using Directive
  21. The Using Directive PPT
  22. Addressability Errors
  23. ADDRESSA (assembler code)
  24. Add and Subtract Packed Decimal Video
  25. Add and Subtract Packed Decimal PPT
  26. Debugging an S0C1
  27. Debugging an S0C4 Video
  28. Code for S0C4 Video
  29. Debugging an S0C7 Video
  30. Code for S0C7 Video
  31. Debugging an S0C7 (Part 2) Video
  32. MVO Video
  33. MVO code
  34. MVO1 code
  35. MVO2 code
  36. MVO3 code
  37. Debugging an S0C9 Video
  38. SC09 code
  39. SRP
  40. BASR
  41. What you can learn from the Cobol Compiler
  42. Conditional Assembly and Macro Processing (PPT)
  43. Conditional Assembly and Macro Processing Part 1
  44. Conditional Assembly and Macro Processing Part 2
  45. Writing Reentrant Code (MP4) (Sample Code)
  46. Using COM Control Sections (MP4)(Sample Code)
  47. Introduction to VSAM for Assembler Programmers (MP4)

Grande Arithmetic

How to use the Visual Prompts for Grande Arithmetic (MP4)
Visual Prompts For Grande Multiplication (pdf)
Visual Prompts For Grande Addition (pdf)
Visual Prompts For Grande Subtraction (pdf)
Visual Prompts For Grande Division (pdf)

Notes On Individual System/z Instructions

The following table contains links to articles about many instructions used in the IBM System/z architecture. Each article contains a description of an instruction, example uses of the instruction, and “tips” on technique.


VisibleZ Video Demos (under construction)



50 responses to “IBM Mainframe Assembler

  1. brian long

    the video “a first program” is not complete, can you please tell me where the rest of it is please?

  2. brian

    i am so sorry but even that link still only plays 4mins16secs of the video? is it possible for you to email me it, i am trying to learn assembler and am really interested in watching this as it looks really good and very clear. Sorry for being a pain. Brian.

  3. Sankalp Mathur

    Respected Sir,
    All your videos are really of great help. I request you to please post a video which can demonstrate the functioning of Move with Offset instruction(MVO). I would be greatful to you Sir.

  4. Anonymous

    I’m currently learning mainframe assembler and your videos are really helping me get up to speed quickly. Having a voice track along with the visuals is priceless. I really appreciate that you have this content openly available.

  5. Thanks for taking time to send your thoughts … I really appreciate that.

  6. ranjeevan

    Hi, these videos are pretty good for a learner.. I appreciate that.
    Also, do you have any videos on useful tips on assembler to cobol conversion?

    • I don’t currently have any videos that address that directly. I am thinking about releasing my Cobol course videos which relate the Cobol datatypes to assembler datatypes.

  7. Hi,
    There seems to be a small error in the video titled ‘SS1 Instructions, MVC, CLC, Branching, Fetch/Execute Cycle’ around the point where you are explaining CLC op code and the instruction ‘CLC Z,X’.

    The remaining two bytes of X will not come from Y because we have defined X as DC of length 5. So we are going to get two bytes of spaces on the right in X. Please correct me if I am wrong.

    Thanks for all your videos. I am learning a lot.

  8. Tong Kongswang

    Hi, I am trying to restore back my Assembler programming skill. I wonder if you have real situations on using ICM and STCM. Thanks. Kongswang

    • ICM is sometimes used to load a fullword into a register when the the fullword in memory is not properly aligned. A load instruction would cause a warning from the assembler, but ICM will not. In a similar fashion STCM can be used to store a fullword into an unaligned field in memory. Keep in mind that ICM doesn’t sign extend the register when it inserts a value like LH does.

  9. Arumugam

    In UNPK video (@03:19), example instruction shows UNPK X,Y, here we are upacking OPR2 to OPR1 that is OPR1 should be a zoned decimal.
    I think the instruction should be UNPK Y,X instead of UNPK X,Y. Similary the next example too should be reversed. Thanks.

    • Thanks for pointing out the error. I updated the powerpoint file to be correct and added a callout to the video that points out the problem. Many thanks for taking time to let me know!

      • Arumugam

        Thank you, all the videos are very helpful. I have a quick question.
        whats the difference between BASR and BALR? I see, most of the programs which we work use only BALR before USING *,R12.

      • BASR was introduced when address sizes changed from 24 to 31 bits. Addresses can now be 24, 31 or 64 bits. BALR saves a 24 bit address and some other information from the PSW. BASR saves a 31 or 64 bit address depending on the addressing mode you are running in. It is safer to change older programs to use BASR instead of BALR since you are probably not running in a 24 bit addressing mode. All new code should use BASR. In most cases you won’t notice a difference, but an older program that uses BALR on a newer machine may cause a problem.

  10. Arumugam

    Just curious, what is the significance of DC X’FFFFFFFF’ before DCB declaration in your soc9 program?? Thanks.

  11. kishore

    Hello sir this videos are very Helpful to learn Asseembler

  12. Awesome courses!! Have you got the PPTs for the first videos on the list? I need that for reading it again without the video. Thanks for your effort!

  13. Bob

    This is an awesome website. I really like the tutorials. It would be good if you created a channel on youTube and then I could watch the videos on TV 🙂

  14. Wilsu

    Many thanks for this site. I just started using IBM Assembler at work and this has helped me out a LOT so far!

  15. Venkat

    Could you please share your thoughts on this..
    AP =X’111C’,=X’119D’

    How would assembler responds when it encounters both operands on AP as literal a.

    Thanks much in advance!

  16. Girish

    Could please let me know,why cc=2 not set in TM instruction?

    Thanks in advance!!!!!!!!!!

    • There are only 3 possibilities when testing bits:
      1) All the tested bits are zeroes – In this case we can use the mnemonic BZ and think Branch all zeroes (instead of Branch zero) BZ tests condition code 00 = 0
      2) All the tested bits are ones – In this case we can use the mnemonic BO and think Branch all ones (instead of Branch on Overflow) BO tests condition code 11 = 3
      3) The tested bits are mixed (some 1’s some 0’s) – In this case we can use BM and think Branch Mixed (instead of Branch Minus) BM tests condition code 01 = 1
      So… condition code 10 = 2 was left out so we could get double use out of the other mnemonics we have. (BH or BP is used for condition code = 2)

  17. Hi Dwool Bright,
    In the house keeping section like the one below
    STM R14,R12,12(R13)
    BASR R12,R0
    USING *,R12,R11
    LA R11,2048
    LA R11,2048(R11,R12)
    1. What if BASR R12,R0 is not precede USING *,R12,R11?
    2. USING (base address), REGISTER
    does USING directive says assembler to treat particular Register as a base register with the mentioned base the above case * i.e current location counter..well if that is the case why we need BASR R12,R0 ?

    3. What if I write like
    STM R14,R12,12(R13)
    BASR R12,R0
    LA R11,2048
    LA R11,2048(R11,R12)
    USING *,R12,R11

    there is no address resolution being calculated in both LA statements so is it a right way to set Base register?..will there be any issues with Domain regarding R11 and R12?

    Thanking you in advance!

    • Venkat,

      I think I may have missed your email of several months ago. Many apologies. I will respond underneath in bold.

      Hi Dwool Bright,
      In the house keeping section like the one below
      STM R14,R12,12(R13)
      BASR R12,R0
      USING *,R12,R11
      LA R11,2048
      LA R11,2048(R11,R12)
      1. What if BASR R12,R0 is not precede USING *,R12,R11?

      If you coded this USING *,R12,R11

      BASR R12,R0

      The base address for R12 would be the address of the BASR, but then BASR R12,R0 would load the address of the BASR plus 2 into register 12. You will be off by two bytes on every base/displacement address

      2. USING (base address), REGISTER
      does USING directive says assembler to treat particular Register as a base register with the mentioned base the above case * i.e current location counter..well if that is the case why we need BASR R12,R0 ?

      The USING tells the assembler which registers to use when converting symbols to base/displacment addresses. So a symbol like X might be converted to a base/displacement address like C008 (C = Base register 12, displacment = 008). But what happens when the machine executes an instruction with this address? It takes the contents of R12 and adds 008 to get the effective address of X. So at run time it is critical that R12 contains the runtime base address. It is the job of BASR to put the base address in the register at runtime. If it’s not there we won’t find X.

      3. What if I write like
      STM R14,R12,12(R13)
      BASR R12,R0
      LA R11,2048
      LA R11,2048(R11,R12)
      USING *,R12,R11

      there is no address resolution being calculated in both LA statements so is it a right way to set Base register?..will there be any issues with Domain regarding R11 and R12?

      This won’t work because the address of the first LA is loaded by the BASR into R12. But then we later tell the assembler the base address is an address of the first instruction following the USING which occurs further down. When we use R12 in a base/displacement address, we will have the wrong contents in R12.

      You also asked about AMODE and RMODE in a different email. AMODE determines how many bits we will use when computing a base/displacement address – the possibilities are 24, 31, and 64. Very old programs were written with 24 bit addresses. Most programs are written with 31 bit addresses. Very large programs us 64 bit addresses.

      RMODE controls where a program lives in memory:

      RMODE 24 – The control section should be loaded below the 16MB “line”.

      RMODE 31, ANY – The control section should be loaded below the 2GB “bar”, either above or below 16MB

      RMODE 64 – The control section may be loaded anywhere in memory.

  18. Les Kelley

    I agree with earlier “this is an awesome site” – presentation and training are excellent.
    A couple of points –
    * in many years of MVS systems programming, I’ve lived the “SAVE/RETURN” entry and exit linkages. Partly because it’s usefulness for debugging, and partly from being burned years ago with an inappropriate BALR/SVC-03 usage.
    * Secondly, I think that in the “jumping-into-branches” document the last page has syntactically wrong examples.
    I currently do not have a mainframe to work on, but z390-ASM is excellent, and the results are as I suspected.
    LARL Rx,Ry+offset should be LARL Rx,Address+offset
    LARL Rx,Named-field
    LA Rx,Ry+offset should be LA Rx,offset(,Ry) where offset is < 4096
    000000 (1/7)7 LWK01 CSECT ,
    000000 18CF (1/8)8 LR R12,R15
    000002 (1/9)9 USING LWK01,R12,R11,R10
    000002 C0B00000100C 00100C (1/10)10 LARL R11,R12+4096
    000008 C0A00000100B 00100B (1/11)11 LARL R10,R11+4096
    00000E (1/12)12 ***
    00000E C0B0000007F9 001000 (1/13)13 LARL R11,LWK01+(1*4096)
    000014 C0A000000FF6 002000 (1/14)14 LARL R10,LWK01+(2*4096)
    00001A (1/15)15 ***
    00001A C0B0000007F3 001000 (1/16)16 LARL R11,OFF4096
    000020 C0A000000FF0 002000 (1/17)17 LARL R10,OFF8192

    00003A (1/25)25 ***
    00003A 41B0080C (1/26)26 LA R11,R12+2048
    00003E 41B0080B (1/27)27 LA R11,R11+2048
    000042 41A0080B (1/28)28 LA R10,R11+2048
    000046 41A0080A (1/29)29 LA R10,R10+2048
    00004A (1/30)30 ***
    00004A 41B0C800 (1/31)31 LA R11,2048(,R12)
    00004E 41B0B800 (1/32)32 LA R11,2048(,R11)
    000052 41A0B800 (1/33)33 LA R10,2048(,R11)
    000056 41A0A800 (1/34)34 LA R10,2048(,R10)
    00005A (1/35)35 ***

    • Sorry, Les, for the long delay in responding. The Christmas vacation has kept me busy and I am just today finding your comment. Thank you for taking time to write – I do appreciate it and depend on all the astute assembler programmers out there for help. Of course, you are absolutely right about the syntax error at the end of the article. I simply dropped the ball. (Punctilious is a goal and not something I have mastered.) I have updated the Jumping Into Branches article to contain what should have been there in the first place. Take a look and see what you think. I am intrigued by your first point … would you mind elaborating a bit? Many thanks – David

  19. francesco mazzon

    ciao from Italy,
    many thanks for your useful website.
    as a joke, could you show briefly how we can code a program using only object code (taken from listing)?
    I mean, maybe in order to “hide” my source, which are the rules to write “90ECD00C” instead of “STM R14,R12,12(R13)”? is there still some part of source I have to write in “clear”? hoping I was clear

    • I assume you are asking how to write a program in VisibleZ. You mentioned the object code 90ECD00C which appears on the left side of the listing and which represents a hexadecimal representation of the binary code. To run that in VisibleZ you could create a text file that represented each byte of object code as two characters separated by white space, so 90 EC D0 0C would work. Take a look at some of the code snippets in the Codes directory. I am now supporting the conversion of z390 programs (mainframe emulator) to a VisibleZ format, so you can take certain mainframe programs and convert them to run in VisibleZ.

      • Francesco,
        Thanks for the comment. If I misunderstood, let me know, and I’ll try again. – David

      • francesco mazzon

        Hello David, thank you for your answer. I’m working on a real MF.
        But I think it will work (maybe without blanks in my case).
        In my environment I found program sources like this:
        MAZXTEST CSECT , xx
        DC X’47F0F01400C3C5C5…. ‘ and lots of DC X’…’ lines until a final END (this in clear!)
        I was wondering if I could write a text file by simply copying from the object code listing or some special behaviour was needed for DSs and DCs.
        thanks gain. francesco

      • You might want to code PRINT ON,DATA,GEN at the beginning of the program so you can see all the DS’s and DC’s and what they generate. You will have to account for those. If you can download your program to a PC you can run it through z390 and produce a .390 file that VisibleZ will convert to my text format.

  20. Rahul

    Hello, Could you please explain the complete difference between Jump and Branch instructions.

  21. Melvyn Maltz

    Not sure how to open a new thread here, but this is one

    You would have thought that with over 50 years of Assembler Programming behind me there’s not much more to learn

    New mainframes, new techniques and new versions of HLASM means it’s still a changing world and I have to keep up with the changes

    For those who like a challenge, tell me what the difference is between these two instructions
    LH 1,=X’FFFF’
    LHI 1,X’FFFF’

    Got it yet…

    Ok, apart from the obvious, that LH loads a DC-type from storage and the LHI loads it from an immediate, according to the PoOP manual there is no difference in operation…”the second operand is sign extended and …”

    Well, the LHI is an invalid instruction and won’t assemble…phoo
    Any numeric value in an instruction operand is converted to a 32-bit signed value and as LHI is algebraic, 65535 is out-of-range

    I am working with the HLASM team to resolve this

    Isn’t Assembler life fun 🙂

    If any guys out there would like to have another mentor (sorry David, don’t want to depose you) then feel free to contact me

    And I’ll mention our free Assembler emulator at

    Melvyn Maltz.

  22. Hi!

    I’m learning IBM Assembler for a course at school

    My question is this one, can I use a label as a displacement for a base?

    something like


    Being DISP a labet with the correct size and type? (which I do not know, by the way)


  23. Nunya Bidnez

    Video 38. SC09 code
    I am reasonably certain that ABEND code is unused.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.