# QB Times Issue #6

## ASM part 3 & 4

By abionnnn

learn asm in 1 hour flat

Lesson no.6 8-bit registers

There are alot of stuff I left out in the last issue for the sake of simplicisty. I've also done a complentary tutorial included called "segments tutorial". These are some of the registers and their uses. 8-bit registers are simple to understand. Let take a small look, remeber you don't have to get what all these mean yet, just browse through them, we'll get back to them later on. First I'd like you to pay attention to the first three
```Register        Use
========        ====
AX              Calculation and Main register
|__AL           Low byte and Int function index (Lower AX) 8-bit register
|__AH           High byte (Higher AX) 8-bit register
BX              Calculation and basic Pointer
|__BL           Lower bit (Lower BX) 8-bit register
|__BH           High bit (Higher BX) 8-bit register
CX              Calculation and counter
|__CL           Lower bit (Lower CX) 8-bit register
|__CH           High bit (Higher CX) 8-bit register
DX              Calculation and Data
|__DL           Lower bit (Lower DX) 8-bit register
|__DH           High bit (Higher DX) 8-bit register
SI              Pointer
DI              Another pointer
BP              "Byte Pointer" mainly used to access stack and preform data movement
SP              "Stack Pointer" Points to first byte to the stack
IP              Code pointer points to current byte of code
CS              "Code Segment" Points to segment of current code cannot be changed,
and even if it can would crash your system.
DS              "Data Segment" Points to segment of data area
ES              Extra segment, for use in misc. function
FS              Same as above
GS              Same as above
```
We all know what is AX and how AX is used. We all also know it's a 16-bit register (like an integer). But what in a blue moon is AL and AH? Quite simple, really. AH and AL are respectably the higher and lower bytes of AX.

Here's an example:

AX=1004

in binary

```AX=     0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 0
| | | | | | | | | | | | | | | |
\-------------/ \-------------/
Higher Byte      Lower Byte
```
Well we have a number in AX (1004), when writen in binary it equals 0000001111101100. But what if we split it into two bytes? One we'll call the Higher Byte AH and we'll call the Lower Bit AL. So, if AX=1004 then,
```AX=     0 0 0 0 0 0 1 1   1 1 1 0 1 1 0 0
| | | | | | | |   | | | | | | | |
\-------------/   \-------------/
Higher Byte        Lower Byte
= AH               = AL
```
AH = 00000011 = 3
AL = 11101100 = 236

It is also interesting to know that thanks to AH and AL, you could manipulate AX in many ways. Here's a formula you really might find handy:

AX=AH*256+AL

Now that you know how AX, AL and AH behave, I can safely tell you that (as you have probably assumed) this counts to BX, CX and DX as well.

Lesson no.7 Segment Registers and memory

It is very important to know your Segment registers. The ones you'll often see are CS, DS and ES. These are used almost all the time to access parts of the memory. You can't address a segment practically without using a segment register. The disadvantages of these Registers though is that they are rather slow, and you can't address them an immediate value. = (

There are techniques around this for example:

```mov ax,segment
mov ds,ax
```
You can use segments to address parts of the memory, much like POKE and PEEK. But you also need an offset (if you have'nt already,which you should by now, read the segment tutorial). To use an offset is rather simple, you can put your offset in di,si,bx or dx (which ever one picks your fancy) and you put square brackets around it. That is practically an offset pointer. Here's an example:
```MOV BX,140h     ;Offset
MOV AX,3h       ;Value to poke
MOV [BX],AL     ;why AL? because we only want to poke 1 byte (8-bit)
```
This basically goes pokes 3 into the memory location 140h. But what segment you might ask? As QB has DEF SEG to address the default data segment, your processor uses the DS register for that job. So really you are writing 3h to DS:0140. Here's an example using a diffrent segment.
```MOV BX,140h     ;offset
MOV AX,3h       ;value to poke
MOV CX,0A000h   ;new segment
MOV DS,CX       ;our little trick to change the segment = )
MOV [BX],AL     ;writes 3 to DS:BX
```
This would write 3 to A000:0140. The same code could have been writen like this:
```MOV BX,140h     ;offset
MOV AX,3h       ;value to poke
MOV CX,0A000h   ;new segment
MOV DS,CX       ;our little trick to change the segment = )
MOV DS:[BX],AL  ;writes 3 to DS:BX
```
Which specifies that we want to use DS as the segment. This just makes things look clearer, but is not needed as DS is the default data segment. But what if you don't want to use DS? maybe you want to use CS or ES... You'd simply do this:
```MOV BX,140h
MOV AX,3h
MOV CX,0A000h
MOV ES,CX
MOV ES:[BX],AL  ;writes 3 to ES:BX
```
Pretty simple is'nt it? Well, since you've loyally finished this course you will find the next one more interesting as we get into new and exciting opcodes. These should make your life easier. Also we might be getting on on how to make your own library. All that coming next month!

Before I continue, I'd like to make 2 correction to previous articals.

*****Correction 1: In the segment tutorial I said 2 byte pointers for 32-bit, what I meant to say was 4 byte pointers. Thank god I picked it up while proof-reading it agian!*****

*****Correction 2: In issue#2 I said retf to exit the program. I don't know what I was thinking, but I'm sorry if it crashed your computer. Infact if we meet one day, you can hit me over the head with a stick = P Use retn or better still function 4C like in issue#3*****

Lesson no.8 Basics of The Stack

Lets get on to something a little bit interesting and very important (and even more important if you want to make libraries). You might have read a bit about the "Stack". How the stack works is beyond the scope of this chapter, however I will teach you how to use and abuse it = P

After coding a while, you'll probably think it gets pretty cramed with the small amount of registers you can use. It gets tacky and some times you might want to "backup" a value a register has. There is a way to do this and obviously it involves the stack or I would'nt be mentioning it (hehehe = P). The two fundimental commands to use the stack are:

```PUSH
POP
```
PUSH saves a value of a register (or a memory location but lets not get on to that yet) on the stack, and POP basically takes this value which was saved out of the stack and in the register.

For example:

```MOV AX,3        ;Give AX a value of 3
PUSH AX         ;PUSH AX (3) onto the stack
MOV AX,5        ;Give AX a value of 5
POP AX          ;POP AX off the stack
```
Well, lets take this simple code step by step. First AX is given a value of 3: "MOV AX,3". Then AX is push on the stack: "PUSH AX", after this AX is given a value of 5: "MOV AX,5". To finish it all AX is pulled out of the stack: "POP AX". As you probably (or hopefully as my maths teacher used to say = )) have figured out AX ends up having a value of 3. The reason for this is PUSH AX, pushed the value of AX (which was 3 at the time) onto the stack then at the end, even after AX was given 5, POP AX pops 3 out of the stack and puts it into AX agian.

Now, you might find this handy later on, but you don't have to give AX a register. You can also give it a immediate value! The above code could have been writen like this:

```PUSH 3          ;PUSH 3 on the stack
MOV AX,5        ;Give AX a value of 5
POP AX          ;POP AX off the stack
```
Reading that, you'd relise it's not important what register you pop the value of the stack onto, infact you can re-write the code before the one above like this:
```MOV AX,3        ;Give AX a value of 3
PUSH AX         ;PUSH AX (3) onto the stack
MOV AX,5        ;Give AX a value of 5
POP DX          ;POP DX off the stack
MOV AX,DX       ;Put the value of DX into AX
```
So you pushed the value of AX, being 3, onto the stack and poped it out as DX! And at the end you moved DX into AX (MOV AX,DX). If you run that code, both AX and DX would end up being 3! As you'd realise the stack is very easy to use, but there is one more thing you have to learn. What if you want to push more than 1 register? Would you do something like this
```PUSH AX         ;PUSH AX onto the stack
PUSH BX         ;PUSH BX onto the stack
POP AX          ;POP AX off the stack
POP BX          ;POP BX off the stack
```
Sounds right does'nt it? We push AX, then BX then we POP AX then BX. Sad to say, but it does'nt work like this. Think of the stack, as a stack of papers. You put one paper labeled A on the floor and then put another paper labeled B down on the floor. When you go to pick up the one on the top you don't pick up A but you pick up B! Here's a simple diagram:

First we PUSH AX (put AX on the stack)

```    The Stack
|               |
|               |
|===============| <-- AX
|_______________|
```
Then we PUSH BX (put BX on the stack)
```    The Stack
|               |
|===============| <-- BX
|===============| <-- AX
|_______________|
```
What's at the top of the stack? BX! This is why you can PUSH one register and POP out another one, because the stack does'nt keep track of what you pushed and where you pushed it, it simply pops out the one on the top! If you are ever confused think of "first in last serve", but for now here is another example:
```MOV AX,3        ;Give AX a value of 3
MOV DX,5        ;Give DX a value of 5
PUSH AX         ;PUSHs AX (3) on the stack
PUSH DX         ;PUSHs DX (5) on the stack
PUSH AX         ;PUSHs DX (8) on the stack
POP CX          ;POPs 8 off the stack and into CX
POP DX          ;POPs 5 off the stack and into DX
POP AX          ;POPs 3 off the stack and into AX
```
So AX has a value of 3 and DX has a value of 5. We then push AX then DX onto the stack so it'll look like this:
```    The Stack
|               |
|               |
|===============| <-- DX (5)
|===============| <-- AX (3)
|_______________|
```
When the add DX into AX which gives the value of 8. After this we push AX (which has the value of 8 now) onto the stack agian, so it should look like this:
```    The Stack
|               |
|===============| <-- AX (8)
|===============| <-- DX (5)
|===============| <-- AX (3)
|_______________|
```
The operations to flow are:
```POP CX          ;POPs 8 off the stack and into CX
POP DX          ;POPs 5 off the stack and into DX
POP AX          ;POPs 3 off the stack and into AX
```
When then pop out 8 and put it in CX, then pop 5 out for DX, and finnally 3 out for AX. So it's going to do this:
```    The Stack
|               |
|===============| <-- AX (8) ==> CX
|===============| <-- DX (5) ==> DX
|===============| <-- AX (3) ==> AX
|_______________|
```
So CX=8, DX=5 and AX=3. Pretty simple if taken step by step, and I promise this will be very very handy to you when you start programming biggies. Now, should I make another chapter? Should I? Ah what the heck, it's 1999 (is it? Don't tell me it's over already = P) so lets go have some fun!

Technicals: In a .com (Copy of Memory) file the stack in the memory actually begins at the last byte [of the 64K memory image] and rises by the occasion from there. Too much pushing (and I mean too much) without poping will gradually bring the stack ontop of the actual program trashing it with garbage. (BTW, this is something you don't want for anarchists out there ... heh heh heh)

Lesson no.9 Procedures 2

Now there are two ways of teaching this, one way is the assembler way and the other one is the debugger way (remeber Lesson 5, Diffrent approach). Each have their advantages (learning wise), so we'll use them both.

Here's an example from Lesson 4 (edited because of retf ... hit me)

```1E7D:0100       CALL 200
RETN
...
1E7D:0200       MOV AX,1
INT 33h
RETN
```
Well so we did'nt complicate things, I did'nt explain what the heck 1E7D was. Basically, 1E7D is the current segment the program resides. Now, we already know what CALL does (it's like a SUB) and retn (like END SUB) so in QB it would have looked like this:
```CALL asub
EXIT

SUB asub
...    'Show the mouse
END SUB asub
```
You would probably think that the way above there is quite messy. There is another way however, a diffrent approach. I'll be honest with you though, you'll end up with nearly exactly the same compiled code but the source code will look better. Lets look at the previous example in a diffrent way (and it gives me a chance to further explain the stack):
```.STACK 100h             ;This gives us 256 (100h) bytes worth
;of stack space, where we can push and
;pop

.CODE                   ;This is the code segment (CS)
CALL showmouse          ;CALL the procedure "showmouse"
mov ax,4C00h            ;the prefered way to exit a program
int 21h                 ;Use the function 4C to exit

showmouse PROC          ;like saying SUB showmouse
mov ax,1               ;Use function 1
int 33h                ;of int 33h
retn                   ;return
showmouse ENDPROC
```
Hey, this kinda looks like a .BAS file in a text editor eh? PROC is like SUB and ENDPROC is like END SUB. But remeber, you always have to have the retn at the end it's what gets you back to the main section. Without the retn, your program will most definatly crash, and if you got complex routines that mess with the hard drive to come, you can kiss your computer goodbye. I can't stress enough how important it is to return to the main code section because when you make libraries for QB, you'll probably want control back to your program, not what ever garbage is after your little routine.

Now, on to a part which you've probably been waiting ages for. How to implement such functions in QB. It's all rather simple really, but it does require a linker and a library creator (which ussally come with QB) and a little bit of patience. Compiling and Linking can be a hassel sometimes, but there are make utilities out there to make life just that little bit easier so I suggest you grab one.

First you'd make a assembler file which looks like this:

```.model medium,basic
.stack 100h             ;enough for us and BASIC

.data                   ;Where you would place all your variables
;(explained later,data segment)

.code                   ;the code segment begins here

PUBLIC showmouse        ;Declare "showmouse" to QB
showmouse PROC          ;Like SUB showmouse
mov ax, 1       ;Function 1 of
int 33h         ;Int 33
showmouse ENDP          ;Like END SUB showmouse

END                     ;END the whole thing
```
Notice the PUBLIC up there? Well, that's needed for QB to access the procedure (showmouse) we've made. It's like DECLARE SUB if you think about it. Anyway, from here you'd compile the code as a .obj file then link as a .QLB file like this:
```C:\PROJECT\MOUSE>tasm32 mouse.asm mouse.obj
Turbo Assembler  Version 5.0  Copyright (c) 1988, 1996 Borland International

Assembling file:   mouse.asm
Error messages:    None
Warning messages:  None
Passes:            1

Microsoft (R) Overlay Linker  Version 3.69

Run File [MOUSE.QLB]:
List File [NUL.MAP]:
Libraries [.LIB]: bqlb45.lib
```
TASM is used here, but any other compiler would do just fine, if it can generate .obj files (But I recommend the Borland TASM compiler). Now, you would load up QB using the library like so:
```QB /L mouse
```
When inside QB, you'd make a statment like this:
```DECLARE SUB showmouse
```
That's all there is to it! Well, not quite but we'll learn more later on! I hope your busting with ideas for stuff to put into QB! I'll be back next issue with stuff on linking ASM with QB. Hey that's what this whole thing is about is'nt it? = )

-abionnnn