* -------------------------------------------------------------------------------------------- * | ChaoZers 98/09/14 | | Assembler Tutorial #07 | | -------------------------------------------------------------------------------------------- | | | Basic usage of the INC commands and the BSR & BRA instructions. | *----------------------------------------------------------------------------------------------* Introduction ------------ Now I will learn you a bit object oriented programing in Assembler, I am going to show you how to INCLUDE your own files into your code, and also how to use them! BRA.x ----- BRA (Unconditional branch), lets you "branch" into different areas of you program. This is an instruction that you wont be able to live without! Here is an example of how it works... Main: MOVEQ #1,d0 ;D0=#$00000001 BRA.B Label ;Branches to "Label". MOVEQ #0,d0 Label: ADDQ #1,d0 ;D0=#$00000002 RTS The above should be pretty clear... When you do the (BRA.B Label) in the above code, it jumps to the label "Label:", where the program execution continues, all the way to the RTS. So if we put it in other words, the instruction (MOVEQ #0,d0) is never executed! To simplify things, we could say that BRA is a bit like the GOTO command in basic. But how do you know when to do a BRA.B or BRA.W or BRA.L? It is really very simple, as when you do a branch, the computer adds an offset to the "execution position". Just to make it clear, lets say you are at position "$56", and want to branch to the label "Lab:" wich is on position $68 ($68-$56=$12). So when the computer branches between theese two positions, it adds the offset $12 to the value $56. ($56+$12=$68). To put it in a simple way, we can say that the computer does a "Location+Offset", when branching. So if the offset is a "byte value" you do a BRA.B, and if the offset is a "word value" you do a BRA.W, and so on. Ofcourse you can use BRA.W even if the offset is a "byte value", as a byte value easily fits into a word value. And Ofcourse, when the offset is $12, the value is a "byte value". Look at the previous example and think about how we would do if we would want to jump back to the previous position, after executing "Label:". Here is an example on how to do it... Main: MOVEQ #1,d0 ;D0=#$00000001 BRA.B Label ;Branches to "Label". Main2: MOVEQ #0,d0 ;D0=#$00000000 RTS ;End! Label: ADDQ #1,d0 ;D0=#$00000002 BRA.B Main2 See? Now it executes the whole code, even the (MOVEQ #0,d0). For this we have to branch two times, and obviously, the more we branch, the slower it gets! And as you can see, it looks like a disaster... If we do like this, our code will eventualy suffer from the spagetti syndrome, geting more&more messy every second ;). So what do we do to shorten this down, and still branch in the same way? Well, to do this we use a very useful instruction... BSR.x ----- BSR (Branch to subroutine), also lets you "branch" into different areas of your program. The big difference between BSR & BRA, is that BSR will let you "return" to the "last known area". I will now learn you how to use BSR in combination with RTS (Return from subroutine). Lets begin by using BSR in the above example instead BRA, it would look something like this... Main: MOVEQ #1,d0 ;D0=#$00000001 BSR.B Label ;Branches to "Label". MOVEQ #0,d0 ;D0=#$00000000 RTS ;End! Label: ADDQ #1,d0 ;D0=#$00000002 RTS ;Return to row after (BSR.B Label). This piece of code does exactly the same thing as the one before, and still, it is alot less messy, thanks to BSR. And as you can see, RTS makes the "program location" to jump back to the row AFTER the last known branch, when used with BSR. In this case it jumps back to (MOVEQ #0,d0). To make things more clear, lets talk basic again :). BSR can be explained as a GOSUB, and RTS can in this case be explained as a RETURN. Here is a piece of code, that can help you understand. In Basic: <----> In Assembler: - - - - - - - - - - - - Main: Main: Value=5 MOVE.B #5,Value ;Value=5 BSR.B Label ;Gosub Label GOSUB Label RTS ;End END Label: Label: MOVE.B #0,Value ;Value=0 Value=0 RTS ;Return RETURN Value: DC.B 0 So now when you know the difference between BSR & BRA, and what they do, you are getting ready for some real action! Sit down with AsmOne/AsmPro and experiment a bit with the BSR & BRA instructions. The more practice you get, the better you code! Use the debugger to see how AsmOne/AsmPro behaves when branching, and if your code works as you wanted it to do. Including files --------------- Now comes the really interesting part, including files within your code =). Here is a litle list of the INC commands available in AsmOne/AsmPro... [INCBIN] - Include binary file. [INCDIR] - Include directory. [INCIFF] - Include IFF file. [INCIFFP] - Include IFF palette. [INCLUDE] - Include source. [INCSRC] - Include a source in one of the buffers (0-9). I will only go through the INCDIR, INCBIN & INCLUDE commands, as the other ones are not important to learn, at this stage! INCLUDE ------- This one lets you include a piece of source into the current piece of source. here is an example. INCLUDE "RAM:MyInclude.i" This row will include "MyInclude.i" into the current source. INCBIN ------ With this command you can include a binary file into your source, like pictures & exe files etc. INCBIN "DH1:Ram:MyMoma.raw" After this "MyMoma.raw" will be loaded into the specified memory location. INCDIR ------ With this command you can specify the current ICNLUDE directory, here is an example. INCDIR "DH1:AsmOne/Sources/" After this row, AsmOne/AsmPro will look for its includes in "DH1:AsmOne/Sources/"... Using INC in your source ------------------------ We will now write a program where we have a mainfile and an include file, so hang on to your pants! Lets call the mainfile "Main.s" and the include "Include.i". Include.i --------- First, lets make the includefile, save this file in "RAM:Include.i" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MyLabel: ADD.L #$12000,d0 ;D0+#$12000 SWAP d0 ;Swap low/high part of the longword. RTS ;Return to mainfile! (IF called by BSR) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Main.s ------ And now, lets make the mainfile, save this file in "RAM:Main.s" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Main: MOVE.L #$5000,d0 ;D0+#$5000 MOVE.L d0,d1 ;D1=D0 BSR.W MyLabel ;"Gosub" MyLabel RTS ;End. INCDIR "RAM:" ;Include dir = "RAM:" INCLUDE "Include.i" ;Include the file "RAM:Include.i" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Now, assemble Main.s and look what happens in the debugger! When doing the (BSR.W MyLabel), the execution jumps to "MyLabel:" and executes the ADD & SWAP isntructions , and then returns from "MyLabel:". D0 will, in the end, consist of the value #$70000001. So, as you can see INC is used to make the code more viewable by the programer, because, when you do the inlcude above, all you do is to "insert" that piece of source into the current source, so this is how it really looks like after including: Main: MOVE.L #$5000,d0 ;D0+#$5000 MOVE.L d0,d1 ;D1=D0 BSR.W MyLabel ;"Gosub" MyLabel RTS ;End. MyLabel: ADD.L #$12000,d0 ;D0+#$12000 SWAP d0 ;Swap low/high part of the longword. RTS ;Return to mainfile! (IF called by BSR) See? This is how easy it is to use the INC commands in your programs. Remeber to experiment ALOT, and learn how to handle theese commands, as it is really important. Closing Words ------------- Now would be a good time to get the system includes from someone, or soewhere. You wont need thoose includes for this tutorial, as we will do our own ones, but it might be a good idea to try to find them somewhere anyway, as there is plenty of source out there, that use them! Excercises ---------- 01.What is the main usage of INCBIN? 02.Whats the biggest difference between BRA & BSR? Answers to Excercises --------------------- 01.Its used to include binary files into your source. 02.BSR lets you return to the old position, by a RTS, while BRA does not. 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.