+ All Categories
Home > Documents > Assembly Language Instructions

Assembly Language Instructions

Date post: 14-Apr-2018
Category:
Upload: hammna-ashraf
View: 236 times
Download: 0 times
Share this document with a friend

of 13

Transcript
  • 7/29/2019 Assembly Language Instructions

    1/13

    Assembly Language Instructions

    The CPU has a list of instructions that it understands. DifferentCPUs have different instructions, of course, typically a

    repertoire of between 30 and 70 instructions. Here are sometypical instructions, from the 6502 microprocessor. It's notsupposed to be a complete list.

    As you may have gathered, I am rather keen on the old 6502.It's a bit long in the tooth, but it was the processor in the old SYM-1micro computer, which I grew up on, so it contains a lot of

    happy memories for me (Ah! Happy days!)

    LDA

    This means "Load Accumulator with ..." The instruction can befollowed by any one of several addressing modes:

    LDA #7 This means "Load the accumulator with the number 7".

    The # symbol means the number following it is the directvalue to be loaded into A.

    LDA 810 This means "Load the accumulator with the value inaddress 810" There is no # symbol, so the assemblerknows that it is an address that is specified, not a directvalue.

    LDA1000,X

    This is a more complicated addressing mode. It means"Load the accumulator with the value in address (1000plus whatever is in the X register)." The value in the Xregister is added to 1000, and that's the address where thevalue is loaded from. If, for example, the X register holdsthe value 81, the value in address 1081 is loaded into theA register.

  • 7/29/2019 Assembly Language Instructions

    2/13

    These are just some of the addressing modes that can be usedwith the LDA instruction. I have listed them to give you a tasterof how it is used.

    LDX and LDYThese load values into the X or Y registers. Again, they can beused with a variety of addressing modes, but not all of thesame ones as LDA. For example, there is no LDX 1000,X ofcourse.

    LDX #231 Load the X register with the number 231.

    LDY 60 Load the Y register with the number that is found inaddress 60.

    LDY 100,X Load the Y register with the contents of the address(100+X) i.e. take the value in X, add it to 100 and thatgives the address which holds the new value of Y.

    STA, STX and STY

    The opposite of loading the accumulator and the X and Yregisters is storing them back into memory. These threeinstructions stand for "Store the Accumulator", "Store the Xregister" and "Store the Y register". They have the sameaddressing modes as for LDA, LDX and LDY.

    JMP

    This is jump instruction, which makes the program move to adifferent location. It simply loads the new location into theprogram counter, which specifies the address of the nextinstruction, and when it goes to fetch that instruction, lo andbehold, it's in the new location.

    JMP for the 6502 can be followed by just two addressingmodes:

    JMP This jumps to a given location. In this case, the next

  • 7/29/2019 Assembly Language Instructions

    3/13

    4500 instruction executed is the one at address 4500.

    JMP(300)

    If the address is placed in brackets, then the CPU looks inthat address, and takes the destination from the jump fromthere. For instance, if the address 300 contains the value63017, then that's the address of the next instructionexecuted.

    Conditional Branches

    There are a variety of jumps which don't automatically happen,they only happen if some condition is true. You will rememberthat there is a special register in the CPU that holds a series of"condition code flags" that are set (to 1) or cleared (to 0) by

    various instructions.

    BEQ (Branch if Equal): One of the flags is the Zero flag (Z). Itis set to 1 on two possible occasions.

    Firstly, if an operation produces the value 0. This might meanthat a subtraction took place that left the accumulator holding 0,or a register was incremented (increased by 1) and itoverflowed to give 0.

    Secondly, if the accumulator is compared to another number(using a CMP instruction) and the two numbers are equal. Whathappens when a CMP instruction is carried out is that the valuein the accumulator is subtracted from the value it is beingcompared with. The answer is not stored - after all, it isn't asubtraction instruction - but the answer is used to set the flags.If the answer would have been zero (i.e. the two numbers wereequal) then the Z flag is set.

    The command BEQ performs the jump (a "branch") to aspecified point only if the Z flag is set. If it is clear, BEQ won'tdo anything and control passes on to the next instruction.Typically, the instruction might be used like this:

    LDA #20 Load the accumulator with the number 20

    CMP 466 Compare it to whatever is in address 466

    BEQ xx2 Branch if the two are equal.

  • 7/29/2019 Assembly Language Instructions

    4/13

    INX Add 1 to the X register (i.e. "increment" it)

    BEQ oflow Branch to the point marked "oflow" if it has overflowed tozero.

    ADC #190 Add 190 to whatever is in the accumulator.

    BEQdone_it

    Branch to the point done_it if it has overflowed to 0

    BNE (Branch if Not Equal): This is the opposite of Branch ifEqual. It performs the branch if the Z flag is clear.

    BCS (Branch if Carry Set): Another flag is called the Carry flag(C). It is set whenever an addition causes an overflow - whichcan be thought of as a "Carry out" to another column. The ideaof "carrying" from one column to another is explained in moredetail in the section on the Fetch Execute cycle.

    The instruction BCS makes the program branch to the pointspecified if the carry flag is set to 1 at that point.

    BCC (Branch if Carry Clear): This is the opposite of BCS. Itonly causes the program to branch if the carry flag is clear.

    There are several other conditional branch instructions, basedupon the other flags in the condition code register, but thatshould give you a brief taster.

    Addition and subtraction - ADC and

    SBCThese are the two basic arithmetic instructions. They stand forAdd with Carry and Subtract with Carry. The carry flag is usedin both cases. It is fairly obvious why a carry is needed withaddition, as you may want to add two-byte numbers where acarry is needed from one byte to the next. In the case ofsubtraction, the carry flag acts as a "borrow".

    Consider normal subtraction a moment. If you have a

  • 7/29/2019 Assembly Language Instructions

    5/13

    subtraction sum like this:

    The first part of the calculation is to do 2 - 7. This requires youto borrow from the next column, so that the calculationbecomes 12 - 7, which can be done easily:

    Its the same with binary subtraction. Here is a two-bytesubtraction in binary:

    I have only shown one of the borrows, the one that straddlesthe low and high bytes. This is what the carry flag is used for.The low bytes (the ones on the right side) are subtracted first,and if a borrow is needed, then the carry flag is set.

    JSR - Jump to SubroutineThis is similar to a simple Jump (JMP), except that theprocessor stores the original address before making the jump.A subroutine is similar to a procedure or a function in a higherlevel programming language (such as C++ or Pascal). Whenthe subroutine has finished (i.e. done what it was supposed to),the program needs to be able to transfer control back to theplace where it came from. This is why it needs the originaladdress to be stored, so that it can jump back to it.

  • 7/29/2019 Assembly Language Instructions

    6/13

    The address is stored in an area of memory called the stack.This is explained in more detail elsewhere. The program knowswhen to retrieve the original address off the stack and return tothe main program because it comes across a RTS instruction(Return from Subroutine). This marks the end of the subroutine:

    When the program reaches the RTS instruction it jumps backto the instruction afterthe JSR 2000. Obviously, there wouldn'tbe any point in going back to the same instruction, as the

    program would simply JSR back to 2000 again.

    Incrementing and Decrementing

    The word "incrementing" means adding one to a register. Theword "decrementing" means decreasing it by one. There areinstructions to increment the X and Y registers, INX and INYrespectively, and instructions to decrement the X and Y

    registers, DEX and DEY. However, there is no instruction toincrement or decrement the accumulator.

    The registers in the 6502 CPU can only hold numbers in therange 0 to 255. If a register holds 255 and is then incremented,it then overflows and ends up holding the number 0. This hasthe effect of setting some of the flags (see above):

    LDX #255

    INX X now holds the number 0

  • 7/29/2019 Assembly Language Instructions

    7/13

    Similarly, if a register holds the number 0 and it is thendecremented, it will go "round the world" to the value 255:

    LDY #0

    DEY Y now holds the number 255

    One and Two-byte values

    The 6502 has registers that can only hold one byte values. Thismeans that they can store whole numbers in the range 0 to 255(or -128 to 127 if the numbers are interpreted astwos-complement values). It's the same with the memory -

    that's stored in terms of bytes, and each memory address canhold only one byte.

    So how does the 6502 cope with 2-byte (or multi-byte) values?It uses two bytes of memory to store two-byte values, with thelow byte first and the high byte second. For instance, supposewe had the instruction JSR 2000, which means "Jump to asubroutine at address 2000". This instruction will take up a totalof 3 bytes - one for the operation code for JSR, which in this

    case is 32 - followed by the low byte for 2000 and then the highbyte of 2000. The low byte of 2000 is 208 and the high byte is7, because 2000 = 7 x 256 + 208. The instruction JSR 2000therefore translates to the following code:

    Assembly of a section of code

    Here I have a small section of assembly language code whichcontains some of the features I have been talking about. I willgo through it step by step doing exactly what an assembler

    would do - translating it into machine code. In this example, Ihave made several assumptions:

  • 7/29/2019 Assembly Language Instructions

    8/13

    I assume this is 6502 code. I have used the assemblerconventions present in the built-in assembler in the SYM-1Micro, so labels marking positions in the code are prefixedby a full stop.

    The SYM-1 assembler uses the symbol & to indicate ahexadecimal numbers, so &70 represents the (ordinary)number 112 (i.e. 16 x 7 + 1 x 0). Most assembler languageprogrammers use hexadecimal.

    Here's the code:

    .x1 LDA #6 This point is labelled as "x1"

    CMP &3500 Compare A with what's in address

    hexadecimal 3500

    BEQ loop2 If they are the same, jump to position

    "loop2"

    LDA &70 Load A with what is in location &70

    STA &3500 Overwrite contents of hex 3500 with A

    .loop2 INX Increase X by 1

    BNE x1 If hasn't reached 0, jump back to "x1"

    Let's take this one step at a time. The assembler is translatingthis code to sit at a particular address in memory. This is setup using an assembler directive, which I haven't botheredputting in here. I shall assume that it is translating the codestarting at address 100.

    Firstly, the assembler comes across the label ".x1". It nowknows that the label .x1 refers to address 100 in memory,since that is the position of the assembly at this stage. This isstored in a table showing the addresses that the various labelstranslate to:

  • 7/29/2019 Assembly Language Instructions

    9/13

    Label Address

    x1 100

    Next the assembler comes across the instruction LDA #6.

    Before translating the LDA, it has to determine what theaddressing mode is, as there are different versions of the LDAoperation code to load from different positions. The # symbolmeans that what follows is the direct value to be loaded into A.The operation code for loading A with a direct value is thehexadecimal value A9. The code LDA #6 generates thefollowing code:

    The current assembly position is now address 102 and that iswhere the next instruction is going to be translated to. That

    instruction is CMP &3500, which compares the value in theaccumulator with the value in hexadecimal address &3500.CMP followed by a two-byte address translates to the operationcode hexadecimal CD. The translated code now looks like this:

    Note that the address of the CMP instruction is given with thelow byte (00) first, followed by the high byte (&35). The fact

    that the address is given in hexadecimal means it does notneed any translation to put it into two bytes - just split it into

  • 7/29/2019 Assembly Language Instructions

    10/13

    pairs of hexadecimal digits and there you are. The currentassembly position has now moved on to address 105.

    Now the assembler comes to another instruction, BEQ loop2.This is where it runs into its first problem - The label loop2

    refers to an address later on in the code, one that theassembler hasn't come across yet. This is known as a forwardreference, and it is a problem that all assemblers have to solveat one time or another. In practice, an assembler wouldprobably leave the address blank (0) and fill it in later. Theaddress of a conditional branch (such as BEQ) is a one-bytevalue as it is always relative to the current program position.The operation code for BEQ is hexadecimal F0, so the code is:

    The current assembly position is now address 107. The valuein address 106 will be filled in by the assembler once it knowswhat address "loop2" corresponds to.

    Now the assembler comes across the instruction LDA &70,meaning "Load the accumulator with whatever is in address(hexadecimal) 70". The operation code is not hex. value A9 as

    that is the op-code to load the accumulator with an immediatevalue. The instruction A9 70 would mean "Load the value (hex)70 into the accumulator", not "Load the accumulator fromaddress(hex) 70". Instead, the operation code is A5. In fact,this is a special operation code for LDA which tells it that theaddress to load from is only one-byte (i.e. less than 256). Thisso-called "zero page" mode (all addresses less than 256 are inthe "zero page" of memory) saves one byte. Now theassembled code looks like this:

  • 7/29/2019 Assembly Language Instructions

    11/13

    The instruction STA &3500 does not use the zero page modeas the address is clearly two-bytes long. The command means"Store the accumulator contents at address (hex) 3500", andthis sort of addressing mode is called Absolute addressing. Thecommand translates to 8D 00 35 (with the low byte of theaddress coming first).

    The next instruction, INX, is preceded by the label .loop2. Theassembler must add this address to the list of defined labels.The current assembly position is address 112, so that is thevalue filled in for loop2:

    Label Address

    x1 100

    loop2 112

  • 7/29/2019 Assembly Language Instructions

    12/13

    An intelligent assembler would probably take this opportunity tofill in the address in the BEQ instruction, but most assemblerswould simply go through the assembly code again at the endand fill in the addresses then. Such a system is called atwo-pass assembler, with the forward references like "loop2"

    being filled in on the second pass. It wouldn't just look forabsent addresses, it would assemble the code from scratch,writing over the previously assembled code (which is veryinefficient, as it duplicates the previous effort). This time, ofcourse, it should know the positions that the labels refer to, andany labels that it still can't identify are genuinely absent (andcause an error).

    The instruction INX is only one byte long. The op-code is E8.

    So, on we go! The last instruction is BNE x1, i.e. branch tolabel x1 if the Z flag is not set. In this case, the label x1 isknown, so the address can be filled in immediately. Theconditional branches don't fill in absolute addresses, but onebyte offsets, i.e. one-byte numbers which are addedto the

    program counter to give the new address. When the CPU isexecuting this instruction, the PC is already pointing to the nextinstruction, which will start at address 115 (after the BNE inaddress 113 and the offset in address 114). To jump back tolabel x1, it is necessary to subtract 15 from the programcounter, to put it back to address 100. Subtracting 15translates to an offset of 241 (hex F1). The op-code for BNE isD0, so BNE x1 becomes D0 F1.

    At the end of the assembly, the assembler makes a secondpass through the source code. It repeats the whole of the

  • 7/29/2019 Assembly Language Instructions

    13/13

    operations above, but this time, all the labels should have beendefined. When it comes to the reference BEQ loop2, itcalculates the offset for the jump as +5, so the instructionbecomes F0 05.

    The final assembled code, in hexadecimal, is as follows:

    A9 06 CD 00 35 F0 05 A5 70 8D 00 35 E8 D0 F1


Recommended