# tianjara.net | Andrew Harvey's Blog

### Entries from April 2009.

17th April 2009

[Updated: Clarified what I wrote about the way stacks in AVR work, in the Push/Pop section.]

## Data Transfer Instructions

(Credit: Hui Wu/COMP2121 Lecture Notes)

ld Rd, v
Rd $\in$ {r0, r1, ..., r31} and v $\in$ {x, x+, -x, y, y+, -y, z, z+, -z}

(remember the X, Y, Z pointers)

Can take on three forms,

Syntax Operation
lpm
R0⟵(Z)
lpm Rd, Z
R0⟵(Z)
lpm Rd, Z+
Rd⟵(Z)
Z⟵Z+1

Z contains the byte address while the program flash memory uses word addressing. Therefore the word address must be converted into a byte address before having access to the data on the program flash memory. Example usage, (Table_1<<1 converts the word address into a byte address)

   ldi zh, high(Table_1<<1) ; Initialise Z pointer
ldi zl, low(Table_1<<1)
lpm r16, z+ ; r16=0x76
lpm r17, z ; r17=0x58
...
Table_1: .dw 0x5876
..

IN/OUT:

AVR has 64 IO registers. Example,

in Rd, A
out A, Rd
where 0 ≤ A ≤ 63.

Push/Pop:

The stack pointer (implemented as two 8-bit registers in the I/O space) points to the next free space in RAM above/below (depends how you look at it) the stack. The stack in AVR is part of the SRAM space, and the stack (in AVR) grows from higher memory locations to lower memory locations. I'm talking about the actual value of the address, so 0xFFFF is a higher address than 0xDDDD. This got me a little confused at one stage because if you draw a picture of memory with 0x0000 at the top of the diagram, and 0x0001 below it and so on then in reference to the diagram a stack that is getting larger with PUSH operations is growing upwards (you usually associate higher to lower with down, this is why I got confused).

So the first thing you must do is initialise the stack pointer (RAMEND is a good starting location).

So a push operation,

push Rr

will push Rr onto the stack (ie. put the contents of Rr into the location that the SP points to), and then decrement the SP by 1. Pop has a similar opposite effect.

## Shift Instructions

### Logical shift left

lsl Rd

### Rotate Left Through Carry

rol Rd

Both operation change some status register flags.

## Functions

We dabbed into this in first year but just to revise and extend a little I'll try to reiterate this here.

The heap is used for dynamic memory applications (eg. malloc()).

The stack is used to store return addresses, parameters, conflict registers and local variables and other things.

In passing parameters in WINAVR (C compiler for AVR) for say a function call they are passed by value for scalar variables (eg. char, int, float) and passed by reference for non-scalar variables (eg. array, struct).

Rules are needed between the caller and the callee to resolve issues such as,

• how to pass values and references to a function?
• where to get the return value?
• how to handle register conflicts? (if a function wants to use a register that was previously in use)
• how to allocate and deallocate stack memory to and from local variables?

If a register is used in both caller and callee and the caller needs its old value after the return from the callee, then a register conflict occurs. Either the compiler or the assembly programmer needs to check for this. The work around is to save the conflict registers on the stack.

The return value of a function needs to be stored in designated registers. WINAVR uses r25:r24 for this.

A stack consists of stack frames. A stack frame is created whenever a function is called, and it is freed whenever the function returns.

(Credit: Hui Wu/COMP2121 Lecture Notes)

## Macros

The AVR assembler offers macros. A macro is just a segment of code that you define and can then use by just calling the macro. Basically the macro name is just a place holder for the macro code. When the program is assembled the macro name will be replaced by the code that macro defines. This defines a macro named mymacro,

.macro mymacro
lds r2, @0
lds r3, @1
sts @1, r2
sts @0, r3
.endmacro

We can then invoke this macro with,

mymacro p, q

The p, q are used like arguments. So @0 will be replaced with p and @1 will be replaced by q. In AVR you can used @0 up to @9 in the macro body.

## Assembly Process

The AVR assembler uses a two pass process.

Pass One:

• Lexical and syntax analysis: checking for syntax errors.
• Record all symbols (labels...) in a symbol table.
• Expand macro calls.

Pass Two:

• Use symbol table to substitute the values for the symbols and evaluate functions (eg. low(-13167)).
• Assemble each instruction (ie. generate machine code). For example add Rd, Rr is encoded as machine code as 0000 11rd dddd rrrr.

## References

Wu, Hui. COMP2121 09s1 Lecture Notes.

Tags: avr, comp2121, computing.
14th April 2009

Just some notes on using ADD and ADC (and also a not on compare and branch instructions at the end). (Thanks also to my lab partner who helped me with some of this stuff.)

The registers for AVR are 8 bits long, as noted if I want to store a 16 bit number I need to use two registers, one will store the low byte and the other will store the high byte. eg the 16 bit binary number a = 1111111100000000 (as big endian) would be stored as a_high = 11111111, a_low = 00000000.

Another thing that I've learnt is how addition of multi byte numbers in AVR works. AVR has the instructions ADD (add without carry) and ADC (add with carry). Lets look at a simple case first.

ldi r16, 0b10101010 //the 0b indicates binary (\$ or 0x for hex, nothing for decimal, 0 for octal). loads the binary number 10101010 into register 16.
ldi r17, 0b10101010
add r16, r17

What happens here is,

  10101010
+ 10101010
01010100
c c c c

The carry bit is set, and hence and overflow has occurred. The actual answer is 101010100 but this has 9 bits and cannot fix in the 8 bits of space we have for the result to be stored into r16. Here we used the ADD instruction this means (at least to the best of my understanding, please correct me if I'm wrong) that we ignore what is originally in the carry flag (part of the status register). If we used ADC and the carry flag was set to 1 then when we add the right most bit as above 0+0 = 0 but we have a carry so we would get a 1 in that last bit. We can use this to do multi byte arithmetic.

Say we have,

//a is a 16 bit number 1010101010101010
ldi al, 0b10101010
ldi ah, 0b10101010
//b is a 16 bit number 1010101010101010
ldi bl, 0b10101010
ldi bh, 0b10101010

//to do a+b (and store the result in a) we do
adc ah, bh

We can then extend this to as many bytes as we want. Say we have a 3 byte number spread over the registers of a_0, a_1, a_2 and another 3 byte number in the registers b_0, b_1, b_2. We could add them like this,

add a_0, b_0
adc a_2, b_2

The result would be spread over a_0, a_1 and a_2 (remember though that we can still overflow this).

It was also enlightening (though also a nice reminder) to see how this low level addition works. (when doing 1bit addition (without carry), a + b, the sum = a xor b and the carry = a and b.) (see picture below)

(Credit: Annie Guo, Basics of Digital Systems, COMP2121 Notes)

This concept can similarly be applied to other instructions. For example,

cp a, b
breq label

will compare a and be and branch to the label label if a is equal to b (and if not continue on executing the subsequent instructions). However what if you wanted to compare if a two byte number was equal to a two byte number? Sure you could just repeat the code one time for the low byte and another for the high byte but you can also do this,

cp al, bl
cpc ah, bh
breq label

These cp and cpc instructions use some trickery (well not really but I didn't initially see how this worked, though its quite obvious now) where they modify some flags based on the result of the comparison and then the branch instructions (breq, brne, brlo...) look at the respective flag to see if they should branch or not.

Tags: avr, comp2121, computing.
13th April 2009

Some general notes from an AVR Tutorial that I have found useful and need to reiterate.

• "Only the registers from R16 to R31 load a constant immediately with the LDI command, R0 to R15 don't do that.
• The first register is always the target register where the result is written to!
• Assembler directives always start with a dot in column 1 of the text. Instructions do NEVER start in column 1, they are always preceded by a Tab- or blank character! [There are no restrictions with respect to column placement of labels, directives, comments or instructions.]
• A very special extra role is defined for the register pairs R26:R27, R28:R29 and R30:R31. The role is so important that these pairs have extra names in AVR assembler: X, Y and Z. These pairs are 16-bit pointer registers, able to point to addresses with max. 16-bit into SRAM [(part of the data memory)] locations (X, Y or Z) or into locations in program memory (Z). The lower byte of the 16-bit-address is located in the lower register, the higher byte in the upper register. Both parts have their own names, e.g. the higher byte of Z is named ZH (=R31), the lower Byte is ZL (=R30). These names are defined in the standard header file for the chips. Dividing these 16-bit-pointer names into two different bytes is done like follows:
.EQU Address = RAMEND ; RAMEND is the highest 16-bit address in SRAM
LDI YH,HIGH(Address) ; Set the MSB
LDI YL,LOW(Address) ; Set the LSB"¹
• Define names for registers with the .DEF directive, never use them with their direct name Rx.
• If you need pointer access reserve R26 to R31 for that purpose.
• 16-bit-counter are best located R25:R24.
• If you need to read from the program memory, e.g. fixed tables, reserve Z (R31:R30) and R0 for that purpose.
• If you plan to have access to single bits within certain registers (e.g. for testing flags), use R16 to R23 for that purpose.¹

Sections marked with ¹ are ©2002-2009 by http://www.avr-asm-tutorial.net, from Beginners Introduction to the Assembly Language of ATMEL AVR Microprocessors by Gerhard Schmidt 2003. Used under the supplied license, "You may use, copy and distribute these pages as long as you keep the copyright information with it."

Tags: comp2121, computing.
11th April 2009

There are two sources of law.

• Statutory Law: In Australia Statutory Law is written law set down by parliament. Before a law can come into force, the Bill must pass through both Houses of Parliament.
• Common Law: “Common law refers to law and the corresponding legal system developed through decisions of courts and similar tribunals (called case law), rather than through legislative statutes or executive action. Common law is law created and refined by judges: a decision in a currently pending legal case depends on decisions in previous cases and affects the law to be applied in future cases. When there is no authoritative statement of the law, judges have the authority and duty to make law by creating precedent.” –Wikipedia

Statutory law trumps common law.

In Australia, the legal system can be broadly classified into 4 different jurisdictions:

• Criminal Jurisdiction
• Civil Jurisdiction
• Contract Law
• Tort Law
• Equity

Litigation refers to the process of a lawsuit (when you take someone to court).

• The burden is on the party bringing the action (the Plaintiff)
• Litigation can be costly and something to be avoided
• Consider mediation and arbitration for civil matters

Punitive damages (in contrast to compensatory damages) are damages not awarded in order to compensate the plaintiff, but in order to reform or deter the defendant and similar persons from pursuing a course of action such as that which damaged the plaintiff.

In the area of Contract Law, clicking an OKAY button on a webpage or during installation is legally binding!

In the lecture we took a look at the Microsoft Windows Vista License Agreement. Though I think the iPhone License Agreement is worth taking a look at too.

### References

Ho. Peter S. 2009. Introduction to Law and Contracts.

Tags: law, seng4921.
10th April 2009

## Constraint Checking

If you use the keyword CONSTRAINT, you also need to provide a name for the constraint. However, it is permitted to omit both the keyword CONSTRAINT and the constraint name. In other words constraint definitions can be either

CONSTRAINT constraint_name CHECK ( expression )

or just

CHECK ( expression )

With respect to the expression,

x = NULL --this is always false
x IS NULL --returns true if x is null, and false otherwise
• You should add as many constraints to the database as needed for the data to make sense and is valid. Its probably bad practice to push this off to the application programming level in say PHP. There is probably a lot more to this though.

## Queries

Standard paradigm for accessing DB from app.code:

-- establish connection to DBMS
db = dbConnect("dbname=X user=Y passwd=Z");
query = "select a,b from R,S where ... ";
-- invoke query and get handle to result set
results = dbQuery(db, query);
-- for each tuple in result set
while (tuple = dbNext(results)) {
-- process next tuple
process(val(tuple,'a'), val(tuple,'b'));
} dbClose(results);
• The important point here is as much as possibly you should try to grab as much data as you need from one SQL query with one call to the DB. Rather than just grabbing the whole database and getting the parts you need in the rest of your program (eg. PHP). I can see how this method would be tempting, but I can also see that its a bad approach.

## Views

create view name as select ...

This makes a "virtual table" called name that you can use in your subsequent SQL queries, but the table will dissapear when the connection is closed (or at least this is when I think it dissapears).

## pg_dump

pg_dump dbname > file

This will dump the whole database (in SQL format) to a file. Use -o to ommit the ownership data.

## Enforcing Case

SQL is case insensitive, to enforce case use double quotes. eg. select name as "Foo" from bar;

## Foreign Keys

Just because an attribute in a foreign key does not automatically imply that it is not null. It may be NULL. If  you want the attribute to never be NULL you must add NOT NULL.

Tags: comp3311.
10th April 2009

From Cory Doctorow and the start of Little Brother (pg 5).

Finally, let's look at the moral case. Copying stuff is natural. It's how we learn (copying our parents and the people around us). My first story, written when I was six, was an excited retelling of Star Wars, which I'd just seen in the theater. Now that the Internet the world's most efficient copying machine is pretty much everywhere, our copying instinct is just going to play out more and more. There's no way I can stop my readers, and if I tried, I'd be a hypocrite: when I was 17, I was making mixtapes, photocopying stories, and generally copying in every way I could imagine. If the Internet had been around then, I'd have been using it to copy as much as I possibly could. There's no way to stop it, and the people who try end up doing more harm than piracy ever did. The record industry's ridiculous holy war against filesharers (more than 20,000 music fans sued and counting!) exemplifies the absurdity of trying to get the foodcoloring out of the swimming pool. If the choice is between allowing copying or being a frothing bully lashing out at anything he can reach, I choose the former.