mptst_word.s - translation of 16-bit C aritmetic to assembly

This file demonstrates translating the following C program to assembly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
uint16_t u16_i;
uint16_t u16_j;
uint16_t u16_k;

void main(void) {
  u16_i = 2047;           // u16_i = 2047 (0x7FF).
  u16_i = u16_i + 1;      // u16_i++, so u16_i = 2048 (0x800).
  u16_j = u16_i;          // u16_j is 2048 (0x0800).
  u16_j = u16_j - 1;      // u16_j--, so u16_j is 2047.
  u16_k = u16_j + u16_i;  // u16_k = 4095 (0x0FFF).
}

Declare variables

First, set aside space for some variables to work with. The .bss command instructs the assembler to place the following values in data memory. Data memory starts at 0x1000; locations 0x000-0x0FFF are reserved for special function registers (SFRs).

.bss

Reserve two bytes (16 bits) for each variable using the .space directive. To emphasize the connection between assembly and C, the equivalent C code given above is repeated before its assembly-language translation.

;; uint16_t u16_i;
u16_i:   .space 2
;; uint16_t u16_j;
u16_j:   .space 2
;; uint16_t u16_k;
u16_k:   .space 2

This isn’t used, but makes the MPLAB X v. 1.80 watch window display the size of the u16_k variable above correctly.

u16_bug: .space 2
 

Code

Now, we can write code. First, tell the assembly the following lines should be placed in program memory using the .text directive.

.text

Next, label the beginning of our program. Make the label global (visible outside this file), so the PIC24 can run this after powering up.

.global __reset
__reset:

Our code starts here. The C program above is listed as a comment before each group of resulting assembly statements. Above each C line is a register assignment. After the register assignment comes the input, process, and output steps.

 
  ;; W0       W0
  ;; u16_i = 2047;

Input

  mov #2047, W0

Output

  mov W0, u16_i
 

This statement requires no register assignments.

  ;; u16_i = u16_i + 1;

Input, process, and output

  inc  u16_i

  ;; W0       W0
  ;; u16_j = u16_i

Input

  mov   u16_i, W0

Output

  mov   W0, u16_j

  ;; u16_j = u16_j - 1;

Input, process, and output

  dec   u16_j

  ;;  W0      W1      W2
  ;; u16_k = u16_j + u16_i

Input

  mov   u16_j, W1
  mov   u16_i, W2

Process

  add   W1, W2, W0

Output

  mov   W0, u16_k
 

The code is complete, but the processor doesn’t stop. To give it something to do, loop forever.

done:
  goto     done    ;Place holder for last line of executed code