Next Previous Contents

## 6. The DroidBattles assembler language

The bots are programmed using asm, here I will go through the basics...

## 6.1 Basics of the mnemonics

    All the real work is done by assembler 'mnemonics' These are instructions like for example
    mov, add, in or out. Each mnemonic has between 0-3 arguments.

    Which argument combinations are possible depend on the instruction; but in general there are
    four different types of arguments:

    registers
    registers pointing to memory,
    value
    memory adress

    Registers are small memory cells within the CPU (that DON'T exist in RAM).
    Some of them are "general purpose registers" and can be used for almost
    anything,  some of them are used for special purposes... they are
    either 16 or 8-bit here's a short list:

    ax : general purpose register, also used by some instruction as result
    containers (div, mul, idiv, imul), it's also used by STOSW as the source of the value
    ah : the high byte of AX, Used by STOSB as the source
    al : the low byte of AX

    bx : general purpose register
    bh : high byte of bx
    bl : low byte of bx

    cx : general purpose register, used as counting register for some instruktions that needs
         to know how many iterations they should make (STOSW,STOSB,MOVSB,MOVSW,CMPSB)
    ch : high byte of cx
    cl : low byte of cx

    dx : general purpose register, used as result register for some instruktions (DIV,MUL)
    dh : high byte of dx
    dl : low byte of dx

    eip : Instruktion Pointer, points to the current point of execution in RAM

    sp : Stack Pointer, points to the current stack point in RAM

    bp : Base Pointer, general purpose register (often used as temporary save for sp)

    si : Source Index, used as memory pointer, (MOVSB,MOVSW,CMPSB)

    di : Destination Index, used as memory pointer, (MOVSW,MOVSB,STOSW,STOSB,CMPSB)

    flags : contains the state flags for the CPU

    Registers pointing to memory is a register with an @ before it:

    mov bx,100 ;100 -> bx
    mov ax,@bx ;Mov the contents of memory cell 100 to ax

    Values is just that...:

    mov bx,100

    Note that pure values can't be the destination in an instruction

    Memory adresses are values with an @ before it:

    mov ax,@100 ;Mov the contents of memory cell 100 to ax

## 6.2 Symbols:

    In most places where you use values you can use constants/symbols/labels:

    $myconst 45
    Declares a constant with the name 'myconst' and the value 45. It can be used as such:

    mov ax,@myconst  ;Move contents of memory cell 45 to ax
    mov ax,myconst   ;Move value 45 into ax

    :label
    Declares a constant with the name 'label and the value of the position in RAM that the current
    assembly point is at. This is useful for jumping in code:

    :label
    mov ax,bx
    add dx,cx
    jmp label

    (Nothing stops you from doing 'jmp myconst' or 'jmp 100' or mov ax,label but it's not
    recommended)

    #variable
    Functions about the same as :label, it defines a constant named 'variable' with the value of
    the current position in RAM. It is intended for declaring variables:

    #myvar
    dw 5

    mov ax,myvar puts the _ADRESS_ of myvar into ax and
    mov ax,@myvar puts the _CONTENTS_ of myvar int ax

    There are a number of predefined constants (from version 0.4.1). These are named after your
    hardware and contains the values of the ports they use:

    If you have two CPU:s and they are devices 0 and 5 the following constants are automatically
    declared:
    Name         Value
    CPU0_GetXSize 0
    CPU0_GetYSize 1
    CPU0_GetBattleType 2
    CPU0_GetMyTeam 3

    CPU1_GetXSize 20
    CPU1_GetYSize 21
    CPU1_GetBattleType 22
    CPU1_GetMyTeam 23

    All hardware gets symbols declared like this. If you change your mind and want the second
    CPU in slot 3 instead you would have to change all the values in your code if you didn't
    use these constants.

    This way your code won't be depending on the exact number of your device. (And will as such
    be more portable between different "hardware"). Not to mention it gets easier to read.

## 6.3 The "Red Tape" tags:

    "Red tape" tags are code that in general doesn't assemble directly into runnable code
    but instead affect how the following code is generated.

    %org number
    All code and such is placed in the RAM mem of the bot.
    %org number makes the code that comes after to start being
    assembled to position number.

    Example:

    nop
    nop
    %org 100
    nop
    nop

    If this is the only code in the bot then nop:s are inserted at
    positions 0,1,100 and 101 in the RAM memory

    also, you can make a relative org.
    Example:

    %org 0
    nop
    nop
    %org 100
    nop
    nop
    %org +100
    nop

    nop:s are inserted at positions 0,1,100,101 and 202

    %CPUboot devicenumber

    This tag makes the device devicenumber (assuming it is an CPU) to
    boot at the current position in the code.

    example:

    %CPUboot 0
    :start
    ...
    ...
    ...
    ...
    jmp start

    %CPUboot 1
    :navigate
    ...
    ...
    ...
    ...
    ...
    jmp navigate

    This causes the CPU:s to execute "simultaneously" in different functions
    in the code.

    %CPUstack devicenumber:
    If you use PUSH/POP/CALL or something like that you must set this.
    It functions as %CPUboot only this one sets stack mem.
    If it isn't set stackmem will default to 0.
    And in that case it WILL overwrite code if you execute a PUSH.

    %interrupt interruptnumber:

    If certain events occur, the hardware can
    "interrupt" the current CPU computing and take it to a "service routine".

    Example bot :

    Hardware:

    CPU
    Plasmagun
    timedev

    code:

    :start
    cli       ;No interrupts when we initialize
    out 8,0   ;Set the timers current tick count to 0
    out 9,100 ;Set the interrupt count to 100
    out 10,1  ;enable this device interrupt
    sti       ;enable interrupts

    :loop
    jmp loop  ;infinite loop

    %interrupt 1 ;Here the code for interrupt 1 (timer interrupt) starts
    :service

    out 8,0   ; reset clock count
    out 4,1   ; shoot

    iret
    %CPUstack 0

    This code will make the bot fire a shot every 100 clock ticks.
    Available interrupts are:

    0: Collision/hit (issued by armor device)
    1: Time interrupt (issued by timedev)
    2: Message received (issued by radio)
    3: Armor below a certain level (issued by armor dev) !OBS only enable this int in ONE armor device
    4: Fuel below a certain level (issued by fuel dev) !OBS only enable this int in ONE fuel device
    5: Heat above level interrupt (issued by armor dev) !OBS only enable this int in ONE fuel device

    If you have multiple CPU:s the first CPU with the interrupt flag set
    will get the int (set the flag with sti, clear it with cli).
    If no CPU has the interrupt flag on, no interrupt is issued.
    Entering an interrupt clears the interrupt flag, and executing
    an iret sets the interrupt flag.

    Remember that you need to specify CPUstack if you use interrupts, as
    the adress of where the CPU where when he got interrupted is saved on
    the stack.

    The adresses of your interrupt vectors are stored at the end of your RAM,
    So if you use interrupts 0 & 1 you shouldn't do something with the 4 last
    bytes of your RAM

    db/dw:

    declare byte/declare word...
    Sets the current bytes to the values after db/dw.
    You may have up to 12 values after each db/dw

    example:

    db 0,1,200,3,4,5,4,3,2,1
    dw 12045,10000,14000,950

    comments:

    comments is started with the ; sign

    example:
    ; This is a comment
      nop        ;wait
    ;  ^           ^
    ; mnemonic   comment

Next Previous Contents