banner



How To Move Data In A Register To Memory In 68k

Recently I did some studying on CPU hardware & architecture, and some programming in Assembly language. Specifically the Motorola 68000. We used an IDE & emulator called Easy68K. So this guide/tutorial will be closely linked with that. This mini guide is intended for anyone and any beginner, should be able to get going writing a program. I wont cover everything but I will cover just enough.

computer-language-and-its-types easy68keditor

Jump to section :  Assembly  CPU   Hello World  Number system  Registers  Addressing  Syntax  I/O  Move & Load  Math  Program Flow  Branch/Jump  Loops  Subroutines  Macros  Memory  Variables, Constants, Misc  Practice  Useful Links

What's Assembly?

Assembly language is the closest thing to the hardware. In other words, while your Java, C#, and JS/Python are all abstracted and higher away from the hardware, Assembly is at the bottom, making working with the hardware easy and more efficient. Because then it gets compiled into machine language, stuff your CPU can understand and execute. Its also very structured. You can't do something like this: object.get().modify().set();. In C++ for example, you might say "int foo = 5;". But in assembly, nothing is abstracted, so code looks like this "move  #5, foo".

What's the 68K?

The 68K is a CPU made by Motorola. Its one of the most successful microprocessors and is still in use today. Embedded systems, computers, even game consoles have used it. Its a 32-bit CISC CPU. It has its own instruction set, the topic of this tutorial 😉 . 595px-kl_motorola_mc68000_plcc

How do I write 'Hello World'?

I will assume that you have installed Easy68K, ready to go. If you haven't, go and install it. Now then, writing "Hello World" in Assembly isn't exactly a "1-line program". In Java you might write "System.out.println("Hello World");. Here's Hello World in Assembly. BTW: you don't need to write assembly code in all caps if you don't want to.

;PUT ANY ASSIGNMENTS HERE 	 	ORG $1000 START: 	LEA	MESSAGE, A1 	MOVE.B	#14, D0 	TRAP	#15 	SIMHALT  *PUT VARIABLES AND CONSTANTS HERE MESSAGE	DC.B	'HELLO WORLD',0  	END START        

Let's break all of this down, line by line, piece by piece.

  1. ORG $1000: this tells the assembler that this program will be located and organized in memory at address $1000
  2. START: this is the first instruction of the program, it is also considered a subroutine. Think of it as "int main()".
  3. LEA  MESSAGE, A1: load the message variable into address register 1 (A1). We'll cover this later.
  4. MOVE.B  #14, D0: move the byte, number 14, into data register D0.
  5. TRAP   #15: a hardware interrupt, think of it like typing a key. Basically, it tells the assembler: go and display or read input.
  6. SIMHALT: terminate the program.
  7. MESSAGE    DC.B  'HELLO WORLD',0: this is our string variable, called message, initialized by 'DC.B', and at the end, has a null terminator (0)
  8. END  START: the last line of the program, the program ends here

Lastly, take a look at the comments. Comments in 68K can be written like so:  ;comment   OR  *comment

Decimal, Binary, and Hex…

Working with numbers in 68K means having to deal with more than just decimals. Binary and Hexadecimal are also used.

  • In 68K, a decimal number is specified like so: #2     <———(just the pound symbol means its a decimal)
  • A hex: #$24      <—–(the dollar symbol tells the assembler that this number is a hex)
  • Binary: #%10101010       <—–(the percent symbol says that this number is a binary)

Registers

68K has 8 data registers (D0-D7) and 8 address registers (A0-A7).

Data register? A data register holds data. In the context of 68K, this data is just numbers. If you put a decimal number like 10 in either a data or address register, it will be interpreted as 'A'. Yep, hex is king here.

Address register? An address register also holds numbers, BUT the values in here are counted as addresses. In C, you can define a pointer like so: int *val = 10;. Address registers are just that, POINTERS to an address in memory. If you look at your A0 register and inside it says "00003000", that means A0 is pointing to memory address $3000.

There is a special register, A7. Why is it special? Because its the stack pointer . Yes, you have a stack at your disposal, you can push and pop stuff from it. We'll get to that (see Moving and loading things).

In Easy68K, if you run your program you will get a screen that displays these registers. Get comfortable with it. Play around.registers

Whats Addressing?

In 68K addressing means how you handle sizes of data. It also means how we work with memory and registers. In C++ for example, an integer is not the same thing as a double. A String is not a character.

Notice how in "Hello world", there's the instruction "MOVE.B". Move is the instruction, and ".B" says that we are going to move a byte of data into a register. In 68K, there are 3 sizes to consider:

  • .B (byte) you know, 8 bits in a byte, example: #$FF
  • .W (word) 16 bits in a word, example: #1234
  • .L (long-word) 32 bits in a long-word, example: #00809070

numsys

Addressing in 68K also means how we decide to deal with memory and registers.

  • Data Register to register: doing instructions that involve only data registers. Example:  MOVE.B    D1, D2
  • Data register to address register: MOVE.L   D5, A2   <—–we're moving what's in D5 into A2, so now A2 points something else
  • Immediate data to register:  ADD.W  #1000, D4
  • Immediate data to indirect address register:  MOVE.B   #$AC, (A0)   <—we're moving a value into whatever data A0 is pointing to
  • Immediate data to absolute address:  MOVE.W   #2000, $9000    <—we're moving a value into the memory address 9000
  • Increment:   MOVE.B   #$9F, (A5)+    <–move a value into what A5 is pointing to, then increment A5 address
  • Decrement:   MOVE.L   #00102340, -(A1)   <—decrement the address in A1, then, move a value into the address A1 is pointing to

More on increment/decrement: When you increment and decrement, you are ultimately adding or subtracting by the size you are moving/using from the address. Example:

  • A0 = 000037BC  <— original address
  • MOVE.B #$AC, (A0)+ = 000037BD  <— Byte increments by 1
  • MOVE.W #$EEAC, (A0)+ = 000037BE  <— Word increments by 2
  • MOVE.L #$22AC0044, (A0)+ = 000037C0  <— Long increments by 4
  • MOVE.B #30, -(A0) = 000037BB <– Byte decrement by 1 first, then move the value

Finally, note that if the symbol is on the left side of the register -> -(A2) it is called pre-decrement/increment, meaning the the pointer will advance or decrease before data is moved. Vice versa if the symbol is on the right side of the register -> (A2)+, it means that we first move data, then advance/decrease the pointer.

Syntax

Lets look at the "MOVE.B  #14, D0" instruction again. Notice how after the instruction, we provide a number, or register as a source. Then a destination register, or memory location (INSTRUCTION.SIZE      SOURCE, DEST). Not every instruction has this kind of syntax, but for now, here's some examples:

  • LEA    $4000, A0  ;load address 4000 into A0
  • ADD   D3, D4  ;add what's in D3 to D4
  • MOVE.W   #$ABCD, -(A6)  ;move a word value indirectly to A6 then decrement address
  • SUBI.W    #4, D6  ;subtract 4 from D6

Instructions that don't have similar kinds of syntax:

  • CLR.L   D0  ;clear D0 entirely
  • SWAP  D2  ;swap the top and bottom half of D2 (02347800   —->  78000234)
  • JSR      START  ;jump to subroutine START

Printing and reading I/O

In "Hello world", all we did was print a simple message to console. In Easy68K its called the simulator window. Remember that this tutorial is closely linked with this assembler, so here's how I/O works with it. Notice how we worked with D0 and A1, lets examine those closely:

  • Moving a certain value into D0 yields different results.
    • Example, moving #14 will display a null terminated string without a newline afterwards
    • Moving #5 means the simulator will be reading input from the user
  • Moving a value into D1, like decimal number 10 (in hex it is 'A'), means that a number will will be printed.
  • Loading something in A1, usually means we're going to print a string.
  • NOTE: when all said and done, the final step to displaying to I/O or reading from I/O is writing: TRAP  #15
*displaying decimal a number to console move	#3, d0     *task #3 in D0 lets us display a decimal number move.w	#100, d1   *move the word value 100 into D1 trap	#15        *the number displayed on screen is 100        

RECOMMEND REFERRING TO THIS FOR ALL KINDS OF I/O OPERATIONS: http://www.easy68k.com/QuickStart/TrapTasks.htm

Moving and Loading things

Moving things around loading data is what Assembly is mostly about. I'll go straight to the instructions:

  • MOVE: moves values between registers and addresses
  • MOVEA: moves addresses between address registers
  • MOVEM: this is used to move things to the stack pointer A7. We can move a single register or multiple registers:
    • Example: MOVEM   D0/D1, -(A7)      <—-push D0 and D1 onto the stack
    • MOVEM    +(A7), D0-D1    <—-pop from the stack and store into D0 and D1
    • MOVEM    A0-A6, -(A7)
  • LEA: load a value or address into an address register (LEA   $5000, A1)

Doing Math

68K has instructions to add, subtract, divide, multiply, complement, boolean logic, and shift

  • ADD: adds values between registers or immediate data to register/memory
  • ADDI: adds but you can only add immediate values, no registers allowed for source
  • ADDQ: add quick, sometimes used for incrementing address pointer
  • SUB: subtracts values between registers or immediate data to register/memory
  • SUBI: subtract but you can only subtract immediate values, no registers allowed for source
  • SUBQ: subtract quick, sometimes used for decrementing address pointer
  • MULS: multiply signed
  • MULU: multiply unsigned
  • DIVS: divide signed
  • DIVU: divide unsigned
  • ASL/ASR/LSL/LSR/ROL/ROR: shift the bits in a register, example ->  ASL.B   #4, D7   *shift the value in D7 4 bits to the left
  • NOT: complement bits, example: 1010  —>  0101
  • OR: perform logical OR on bits…    1001  OR  0110 = 1111
  • AND: perform logical AND on bits…   1010 1100   AND   0010  1000 = 0010 1000
add	d0, d1		*add byte contents of d0 to d1 addi.w	#$AABB, d2	*add immediate word to d2 mulu	#16, d4		*multiply d3 by 16 not.l	d6		*complement the longword binary bits of d6 lsr.b	#16, (a0)	*shift the bits of the data pointed to by a0 16 bits to the right divu	#2, d5		*divide d5 by 2 subq	#4, a3		*decrement a3 by 4        

Control and Checking

In all high level languages the if-statement is used for program flow and control/checking. In 68K, we can compare.

  • CMP: you can compare immediate data to register, register to register, and more…
  • Example: CMP.B   #4, D5    ;does the byte value in D5 equal 4?
      • After you compare however, YOU MUST DO SOMETHING, and that's where subroutines come in.
      • Usually after comparing, we branch somewhere.
    CMP.B   #4, D5   *does the byte value in D5 equal 4? BEQ     doStuff  *branch if equal, to a subroutine called 'doStuff'            

Branching and Jumping

Branching means we go to another piece of code, usually a subroutine. Jumping means jumping to a subroutine and then coming back. There's different kinds of branches and jumps.

  • BRA: just branch somewhere, like 'BRA   func1' means go to subroutine 'func1'
  • BEQ: branch if equal (if D0 = 4 then go here…)
  • BNE: branch if not equal
  • BLT: branch if less than
  • BGT: branch if greater than
  • BCC: branch on carry clear (see Condition codes)
  • BCS: branch on carry set (see Condition codes)
  • JSR: jump to subroutine, note , you will need to have 'RTS' at the end of a subroutine should you use JSR
  • JMP: jump. Yes, only jump. You can either jump to a subroutine or jump to a specific address/program displacement. Example: JMP  (A0, D0)

Looping

How would you implement a for loop in 68K? A while loop?

func1:  *for loop example 	cmp.b   #$A, D0   *does D0 equal 10? 	beq	done      *if so, branch to done 	addi	#1, D0    *increment D0 	bra	func1     *else, go back and loop   func2:	*while loop example 	LSR.B	#1, D3    *do a logical shift left 1 bit 	BCS	done      *branch on carry set 	BRA	func2     *loop again  done:         SIMHALT        

Subroutines

You can write subroutines for anything in 68K. Think of them like methods in C/C++. A subroutine must first be defined by a label (the name), then the code afterwards. Example:

doStuff: 	move.b	#5, d0 	move.l	#$00ABC5F0, (a0)+ 	lea	message, a1 	cmp.w	#$FF, a5 	beq	goThere 	addq	#4, d0 	bra	doStuff  doMoreStuff: 	clr.l	d2 	move.l	d2, a2 	jsr     routine2 	rts        

Macros

You can write a macro that will greatly simplify the way you do things. For example, here's a how a print macro looks like (all credit given to Prof. Charles Kelly of Easy68K forums)

*----------------------------------------------------------- * Written by   :  Chuck Kelly * Description  :  Demo of macros * Macro definitions should be placed at the top of the source file. *-----------------------------------------------------------       OPT   MEX CODE   EQU   0 TEXT   EQU   1     SECTION   TEXT    ORG      $2000    SECTION   CODE    ORG      $1000  * print the text string * use ENDL as second argument to add return and linefeed PRINT   MACRO    SECTION   TEXT MSG\@   DC.B   \1    IFARG   2      IFC     '\2','ENDL'       DC.B   $D,$A      ENDC    ENDC    DC.B   0    SECTION   CODE    MOVEM.L   D0/A1,-(SP)    LEA      MSG\@,A1    MOVE.B   #14,D0    TRAP   #15    MOVEM.L   (SP)+,D0/A1    ENDM  HALT   MACRO    MOVE.B   #9,D0    TRAP   #15    ENDM  ********************** *   Program Start ********************** START    PRINT   <'Macro Demonstration Program'>,ENDL     HALT         Halt the program    END   START        

Memory in 68K

Easy68K provides a way of viewing what's going on in the memory we're working with. When you run your program, under the View menu you can click "Memory" and you will get this screen. Inside the blue outline is our current address. In green is the offset. In red is the data residing at that location.

The current address, the data residing, and the offsets.
The current address, the data residing, and the offsets.

Condition codes

When you do math in 68K, certain condition codes are set. For example, if we compare something and its equal, a special bit called 'Z' gets set to 1 that lets us know it is equal. 68K has these things called condition codes:

  • X – extend bit
  • N – negative bit
  • Z – zero bit
  • V – overflow bit
  • C – carry bit

Variables, Constants, Misc

You can also set variables and constants above your code like so…

*you can define stuff here as well address1   EQU   $1500 address2   EQU   $2000 variableX  EQU   #40 ********************** *   Program Start ********************** START     ;put program code here  text    dc.b    'bla bla bla',0       END   START        

Practice!

Anything worth being great at means tons of practice. Assembly language is no exception. To best understand how to program in this language, write programs! Play around in the IDE, look at memory, debug, etc. Here's some ideas for programs to try and get you going.

  1. Write a 68K program to scan a region of memory and look for a specific value. If found, print the address location.
  2. Write a 68K program to take user input, such as your name, and display it to the console. Hint: look into an ASCII table for reference.
  3. Learn about subroutines, jumping, branching, and program displacement by writing small subroutines.
  4. Write a 68K program that takes number input from a user and prints to screen the hexadecimal representation.
  5. Write a 68K program that uses a macro to print the binary representation of a number.
  6. Calculate the Fibonacci sequence using the 68K assembly. Bonus: include a routine that calculates factorial.
  7. Write a 68K program that checks if a string is a palindrome or not.
  8. Write a program that calculates reverse polish notation expression in 68K assembly. Make it so that it can also take user input for the expression.
  9. Create a linked list structure in 68K Assembly.
  10. Make a Towers of Hanoi console based game in 68K Assembly.

Useful Links:

  • http://www.easy68k.com/paulrsm/doc/trick68k.htm
  • http://mrjester.hapisan.com/04_MC68/Index.html
  • http://www.easy68k.com/examples/Cpp%20to%2068K.pdf
  • http://www.nxp.com/assets/documents/data/en/reference-manuals/M68000PRM.pdf
  • http://www.easy68k.com/QuickStart/LoadPageFrames.htm
  • http://www.easy68k.com/features.htm
  • http://www.asciitable.com/

chapter-3-computer-organization-51-638

I hope this tutorial has helped you in any way. Happy programming :). Let me know if I should change or edit anything on here. If you liked this tutorial please rate it and comment on it.

How To Move Data In A Register To Memory In 68k

Source: https://simpledevcode.wordpress.com/2016/12/15/mini-guide-to-68000-assembly-programming/

Posted by: hollandtheres.blogspot.com

0 Response to "How To Move Data In A Register To Memory In 68k"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel