* -------------------------------------------------------------------------------------------- * | ChaoZers 98/08/25 | | Assembler Tutorial #06 | | -------------------------------------------------------------------------------------------- | | | Basic usage of the ADD & ASx & & SWAP instructions. | *----------------------------------------------------------------------------------------------* Introduction ------------ This time i have a great bunch of instructions for you to learn, so be ready for a big feast. First thing to learn -------------------- As with the MOVE instruction, you should use longwords as lilte as you can, because this gains some speed, not always, but mostly. Theese instructions that I am going to learn you now are part of the real basics, so be sure to understand everything! ADD.X (X=B, W, L) ----------------- The ADD.X instruction can handle bytes, words & longwords, and is a very frequently used instruction when programing assembler. This instruction "adds" the source to the destination. Here is an example of how to use it... Start: MOVEQ #5,d0 ADD.B #2,d0 ;D0=#$00000007 RTS See how it works?:).. First we move the value #5 into d0, and we use MOVEQ beacuse we want to clear the whole register. After that we ADD #2 into d0, and the value in d0 is now #7. So ADD is really the same thing as "+". Ofcourse, you can only get a max value of $FF in d0 if doing a ADD.B. So in order to be able to get a higher value than $FF in d0, you need to use words or longwords. Hmm.. but what will happen if you pass the value $FF when doing a ADD.B? Lets take an example... Start: MOVE.L #$ff,d0 ;D0=#$000000ff ADD.B #5,d0 ;D0=#$00000004 RTS Hmmm? How can this be possible then? Well, the reason is that because we use a ADD.B the value wraps around and begins at 0 again, this is because we have passed the max value of a byte. So if we would have written (ADD.B #1,d0) instead, we would have got the value D0=#$00000000 in the above example! So if you dont want the value to wrap around you have to do a ADD.W. Let me show you... Start: MOVE.L #$ff,d0 ;D0=#$000000ff ADD.W #5,d0 ;D0=#$00000104 RTS Easy eh?:) You can also use the ADD instruction with labels and address registers! Here is a final example. Start: MOVE.B #$50,Label ;Label=#$50 MOVE.L #$20,d0 ;D0=#$00000020 ADD.B Label,d0 ;D0=#$00000070 RTS Label: DC.B 0 As you can see above, we save the value #$50 in "Label:" and then later we ADD it to d0. Lets go on to the next ADD instruction... ADDQ ---- This adds a 3bit value to the destination, and it is immidiate (just like MOVEQ is), this means that you CAN NOT do operations like theese... MOVEQ dx,dx MOVEQ Label,dx But in some cases it can (obviously) be pretty smart to use the ADDQ instruction, as it is pretty fast, just remember that you can only add the max value of %111 with the ADDQ instruction. Here is an example! Start: MOVE.L #$fff0,d0 ;D0=#$0000fff0 ADDQ.L #3,d0 ;D0=#$0000fff3 (3 is lower than %111, therefore possible) RTS So as you can see its pretty much the same as ADD.X, only that it is alot faster and can only handle an immidiate adressign mode. And ofcourse, that it can only handle a "max add" of 3bits! This was the last example on the ADD instruction, you will have to do some experimenting on your own in AsmOne/AsmPro, if you dont understand something, (or want to know more). ASx (x=L, R) ------------ This is a very smart instruction, its used when you want to double a value or multiply it (x*2) times. It can also be used as a "divider" and divide your value (x*2) times... Lets warm up with a small example... Start: MOVEQ #$15,d0 ;D0=#$00000015 ASL.W #1,d0 ;D0=#$0000002A RTS Above we first move the value 15 into d0, and then we ASL d0 one time, this will double the value in d0. Check for yourself ($15*2=$2A) or in decmal (21*2=42), this should be easy to understand. But just to be sure, i will take another example, but this time we ASL two times. Start: MOVEQ #$60,d0 ;D0=#$00000060 ASL.W #2,d0 ;D0=#$00000180 RTS Above we move the value 60 into d0, and then we ASL d0 two times, this will double the value twice (ASL.W #2,d0), in d0. Check for yourself, ($60*2*2=$180) or in decimal (96*2*2=384), this should (as the previous example), be pretty easy to understand. Now, let me show you a bit more, what ASx really does, and how it works... First imagine that we have a register, with the value $00000260... $00000260 = %00000000.00000000.00000010.01100000 As you can see the two above values are the same, but what happens if we ASL the value $00000260 one time...?? Then we would get this output... $000004C0 = %00000000.00000000.00000100.11000000 Now look at the two examples... If you look closely, you can probably see that all bits in the binary value have been moved one step to the left. So what happens if we ASL the value $00000260 three times instead? Lets take a closer look... $00001300 = %00000000.00000000.00010011.00000000 See?? The binary value is moved three steps to the left if we do a (ASL #3,dx), this is the same thing as doing VALUE*2*2*2... ASR works the same way as ASL, only it moves the bits to the right instead. Lets take a few more examples... Start: MOVE.L #$500,d0 ;D0=#$00000500 ASR.W #2,d0 ;D0=#$00000140 RTS In the above example we do a (ASR.W #2,d0), and this shifts the bytes two steps to the right. This is, (as you should know by now), the same as VALUE/2/2. So we get $500/2/2 when doing the ASR on d0 in the above example, and this brings out the value D0=#$00000140. ASR means "Arithmetic shift left". ASL means "Arithmetic shift right". Now, lets go a step further... Start: MOVE.L #$82500,d0 ;D0=#$00082500 ASL.W #1,d0 ;D0=#$00084A00 RTS Ok, if you look closely above, you can see that it didnt double the "whole" value, it forgot the 8 in d0. So what we really did above was to ASL the value D0=#$00002500 in the above example, and $2500*2=$4A00. This is obviously because we are using a ASL.W (Word), so to make the ASL command working with the whole value we need to use longowords... Start: MOVE.L #$82500,d0 ;D0=#$00082500 ASL.L #1,d0 ;D0=#$00104A00 RTS See that? Its very simple =)... ASx also works with labels, but then it can only handle words. Here is an example... Start: MOVE.L #$25,Label ;Label=#$00000250 ASL.L #1,Label ;Not possible! MOVE.L Label,d0 RTS Label: DC.L 0 If you try to compile this, the assembler will tell you that ASL.L is an "illegal size". So the above piece of code is not possible... To be able to compile this you need to change ASL.L to ASL.W... Here is a modified piece of code that works perfectly... Start: MOVE.W #$25,Label ;Label=#$00000250 ASL.W #1,Label ;Label=#$000004A0 MOVE.W Label,d0 ;D0=#$000004A0 RTS Label: DC.W 0 Ok... There are a few other limitations, but you will have to experiment on your own... I wont be able to cover everything, so spend some time in AsmPro/AsmOne and figure out as much as you can about the ASx instruction. SWAP ---- The SWAP instruction can be very useful sometimes, what it does is to "swap" the low part of the longword with the high part of the longword. Lets take an example, to illustrate this... Start: MOVE.L #$ffffaaaa,d0 SWAP d0 ;D0=#$AAAAFFFF If ou look at the above piece of code you can probably see that SWAP, "swapped" the low word with the high word. SWAP is used with Data registers. This is pretty much all that there is to it, go on and experiment on your own :). Closing words ------------- I am going to go through alot more instructions, but if you want additional info about different instructions in advance, check out the MC680X0 guide... You can find it at alot of places on the net, and get it from almost any coder. THe MC680X0 guide covers the usage of the MC680X0 proccessor! Excercises ---------- *Theese ones are a bit harder than the others. 01.The ADDQ instruction is good for alot of things, but has a few limitations! Which of theese rows are NOT possible when using ADDQ? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A. ADDQ #2,d0 B. ADDQ #3,a0 C. ADDQ #4,(a0)+ D. ADDQ #20,a0 E. ADDQ Label,d0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *02.What value will d0 consist of after executing this piece of code? I want you to give it to me in binary, decimal & hexadecimal values. Use only paper+pen+calculator to solve this one! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Maincode: MOVE.L #$00045000,d0 ADDQ.L #$5,d0 ASL.L #3,d0 ASR.L #2,d0 RTS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *03.What value will d0 consist of after executing this piece of code? I want you to give it to me in binary, decimal & hexadecimal values. Use only paper+pen+calculator to solve this one! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Maincode: MOVE.L #$50000,d0 MOVE.L #$100,Label ASL.L #4,d0 SWAP d0 ASR.L #2,d0 ADD.L Label,d0 RTS Label: DC.L 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Answers to Excercises --------------------- 01. D & E. (They are not possible with ADDQ) 02. Decimal=#565258 Hexadecimal=$0008A00A Binary=%00000000.00001000.10100000.00001010 03. Decimal=#276 Hexadecimal=$00000114 Binary=%00000000.00000000.00000001.00010100 Email&More ---------- Want to get in touch with me? My email is "chaozer@algonet.se". My homepage is at "http://www.algonet.se/~chaozer/" You can also find me on IRC, almost everywhere, under the nickname ChaoZer.