* -------------------------------------------------------------------------------------------- * | ChaoZers 98/06/29 | | Assembler Tutorial #05 | | -------------------------------------------------------------------------------------------- | | | Basic usage of the MOVE & CLR & DC instructions. | *----------------------------------------------------------------------------------------------* Introduction ------------ Yepp! This time we are going to talk about the most common instruction of the 68K processor! :) Yes, you guessed it, that is the MOVE instruction! First thing to learn -------------------- There are different types of MOVE instructions, so lets talk about what they do. Always try to optimise what you do by moving bytes instead of longwords if you can, because you should keep in mind that you gain speed by doing that... MOVE.X (X=B, W, L) ------------------ This is the MOVE command, and it moves the contents of the source to the destination, let me explain how to use it, so you wont look like a questionmark. MOVE.B - Moves the byte part of the source to the destination. MOVE.W - Moves the word part of the source to the destination. MOVE.L - Moves the longword part of the source to the destination. Uhm... Still not clear enough i guess... So lets look at some examples on this. MOVE.B #13,d1 Here you move the decimal value 13 into d1, keep in mind that the max value we can move when dealing with bytes is 255, as the hexadecimal value $ff=#255 in the decimal system. If you imagine the register d1, it is 32bit and can therefore handle the max value of $FFFFFFFF, or written in binary form it can handle the max value %11111111 11111111 11111111 11111111. So when moving bytes we move the two last hexadecimal values in the register or memory location. Lets take an example. MOVE.L #$33333333,d1 This moves the value $33333333 into d1. D1=$33333333 MOVE.B d1,d2 Now we move the value $33 into d2. D2=$00000033 And now, lets take another example to clear things out even more! MOVE.L #$11111cff,d1 This moves the value $11111cff into d1. D1=$11111cff MOVE.W d1,d2 Now we move the value $1cff into d2. D2=$00001cff See how it works? It is pretty simple, but imagine that d2 is not cleared, and already consists of a value, then the result wont turn out the same, lets take another example! MOVE.L #$34343434,d2 This moves the value $34343434 into d2. D2=$34343434 MOVE.L #$81818181,d1 This moves the value $81818181 into d1. D1=$81818181 MOVE.W d1,d2 Now we move the value $8181 into d2. D2=$34348181 So D2 is holding the value $34348181 in the end, because of the (MOVE.W d1,d2). If we were to do a (MOVE.B d1,d2) in the above example, d2 would have the value $34343481. Its that simple... If you dont understand something, read everything again, because you just HAVE to understand it! The thing you should do now is to play around a bit in AsmOne/AsmPro, because this will make you understand the MOVE instruction even better! :) Here is an example that you can cut/paste into AsmOne/AsmPro! Initregs: MOVE.L #0,d0 MOVE.L #0,d1 MOVE.L #0,d2 ;Clear the registers d0-d2! Maincode: MOVE.B #$10,d0 MOVE.L #$8000,d0 MOVE.W #$1050,d1 ;Put some values in. MOVE.B d1,d0 RTS When you have pasted this into AsmOne/AsmPro you can check out what the assembler does when compiling this, do this by pressing SHIFT+AMIGA+D when in command mode, this will take you into the debugger, which is the most important tool around =). When in debugging mode, use the cursor keys to go forward in the code, and now watch what happens with the registers! More complex usage of MOVE.X & and an introduction of DC.X ---------------------------------------------------------- Ok, now you know how to move values into registers, and also how to move values in registers into other registers. Now i am gonna show you a few other adressing modes. Here is a small example! Label EQU 5 ;Label=5 Maincode: MOVE.B #Label,d0 ;d0=#$00000005 RTS After this D0 is holding the value #$5, as you can see, so (MOVE.X #Label,dx) moves the value in Label into dx, you can check it out by yourself using the debugger! Here comes another important example... Maincode: MOVE.B Label,d0 ;d0=#$00000020 RTS Label: DC.B $20 So, above d0 contains the value #$20 after execution. So when doing the (MOVE.B Label,d0) you move the value in "Label:" into d0, and as you can see "Label:" consists of the value $20! "Label:" is positioned somewhere in memory, the assembler chooses where to put it, so now you only take up a byte in memory, as of DC.B, if you would write DC.W you would take up two bytes, and if writing DC.L you would take up four bytes of memory. Lets take another example! Maincode: MOVE.W Label,d0 ;d0=#$000009C4 (#2500) RTS Label: DC.W 2500 Above we declare a decimal value in "Label:" instead of a hexadecimal value, and as you probably have guessed the decimal value #2500 is the same as $9C4 in hexadecimal. Now you should understand a bit of what the DC instruction is used for. Try out the things you have learned in AsmOne/AsmPro so you really understand everything! Ok, now lets go on. DC also makes it possible to have several values under a label! Here is an example of how to do it! Maincode: MOVE.W Label,d0 ;d0=#$00001500 MOVE.W Label+2,d1 ;d1=#$00000800 RTS Label: DC.W $1500 DC.W $800 ;2 values in here. Above we have two values in "Label:" and we move one of them into d0, and the other one into d1. Maybe you are wondering why we do a +2 in (MOVE.W Label+2,d1)? This is because the values under Label are words, and words take up two bytes of memory, therefore we have to jump two bytes into memory to be able to reach the second value! Lets take another example on this! Maincode: MOVE.L Label,d0 ;d0=#$15000000 MOVE.L Label+4,d1 ;d1=#$08000000 RTS Label: DC.L $15000000 DC.L $08000000 ;2 values in here also! Above we have two values in "Label:" once again, and we move them into d0&d1. The difference in this example, compared to the previous one, is that we are dealing with longwords instead of words! So because we are using longwords, we have to do a +4 at the second MOVE instruction, because a longword takes 4 bytes of memory. You can also make use of address registers, let me explain closer, with an example. Maincode: MOVE.L #Label,a0 ;Move Label adress into a0 MOVE.L (a0)+,d0 ;d0=#$15000000 MOVE.L (a0),d1 ;d1=#$08000000 RTS Label: DC.L $15000000 DC.L $08000000 ;2 values once again... So in the above example d0 consists of the value $15000000 and d1 consists of the value $08000000, after execution. I will explain exactly what happens above. First, when we do the (MOVE.L #Label,a0), we move the address of "Label:" into a0, in other words, we move the location of "Label:" into a0. I might aswell repeat that the address is WHERE in memory the label is positioned. If we were to do a (MOVE.L Label,a0) instead, we would move the VALUE of "Label:" into a0, this would, in this case, be the value #$15000000. So this is the difference between writing #Label & Label. Second, when we do the (MOVE.L (a0)+,d0), we move the "contents of the address in a0" into d0. Let me explain this a bit better... When we did the (MOVE.L #Label,a0), we moved the "Label:" address into a0, so after this a0 consists of the "Label:" address. So the thing we do when doing a (MOVE.L (a0)+,d0) is that we move the contents of "Label:" into d0... This is because the "Label:" address is positioned in a0. If we were to write (MOVE.L a0,d0) instead, we would have moved the value in a0 into d0. So the () signs are the ones that tell the assembler to "move the contents of the address in ax into dx". What the hell does the "+" sign do then, you probably wonder?:) Well, the "+" sign increases the value in aX with x number of bytes. If you do a MOVE.B it increases aX with 1 byte, if you do a MOVE.W it increases aX with 2 bytes, and if you do a MOVE.L it increases aX with 4 bytes. In the above example we do a (MOVE.L (a0)+,d0), therefore a0 will be increased with 4 bytes. So if we do this, we can suddenly get hold of the value $08000000 from "Label:" if we do a (MOVE.L (a0),d1), and this is exactly what we do on the next line! So (MOVE.L (a0)+,d0), FIRST puts the value into d0, and AFTER that it increases a0, easy, eh? Phew! That text is a bit messy to read, i suposse... If you dont understand it read it again untill you get it :). When we are at it, i will show you another way of manipulating with address registers! So here comes an example, sharpen your braincells! Maincode: MOVE.L #Label,a0 MOVE.L (a0)+,d0 ;d0=#$15000000 MOVE.L (a0)+,d1 ;d1=#$08000000 MOVE.L -(a0),d2 ;d2=#$08000000 RTS Label: DC.L $15000000 DC.L $08000000 DC.L $01000000 Yes, this one is ALMOST the same as the previous example... Look at the row with (MOVE.L -(a0),d2) here it does almost the same thing as (MOVE.L (a0)+,d2), but there is a big difference, instead of increasign the register with x bytes, it decreases it with x bytes. There is another big difference, (MOVE.L (a0)+,d2) would FIRST put the value into d2 and AFTER that it would increase a0. But (MOVE.L -(a0),d2) FIRST decreases a0 and AFTER that puts the value into d2. So its pretty simple to understand! This is why we get d2=#$08000000 instead of d2=#$01000000. You can also save a value under a label, that can be done like this... Maincode: MOVE.L #$30,d0 ;D0=#$00000030 MOVE.L #$15,Value1 ;Move the value $15 into the label "Value1:" MOVE.L d0,Value2 ;Move $30 into the label "Value2:" as this now is the value of d0! MOVE.L #0,d0 ;Clear d0! (Will be explained later...) MOVE.L Value1,d0 ;D0=#$00000015 (Here we fetch back the saved value!) MOVE.L Value2,d1 ;D1=#$00000030 (here we fetch back the saved value!) RTS Value1: DC.L 0 ;=#$15 Value2: DC.L 0 ;=#$30 Now look above, i save the values in two different ways, one is moving from a register into a label, (MOVE.L d0,Value2) and the other one is moving a value directly into a label, (MOVE.L #$15,Value1), and yes it is possible to save values in more ways than this! One possibility can be (MOVE.L (aX),