How exactly do you create a loop with Assembly language

specs365

Joined Mar 14, 2019
29
Hi everyone, I understand this is a very basic question, but I'm still very new to assembly. I would just basically like to understand what the the following means:
=> The F and A after the decfsz command.
=> how do I know how many time the loop will execute (Probably something to do with the above question).

Here is my code. I'm just trying to flash some LEDs with a period of 1s

P.S. I'm not really sure if the decfsz command is used correctly.
Code:
; -----------------------------------------------------------------------------
; EMK310
; Example code 1.1
; Basic assembler program structure
; Lecturer: Prof T Hanekom
; Date of last revision: February 2016
;------------------------------------------------------------------------------
; SIMULATION, i.e. use SIMULATOR
; Check list:     1*. Simulation (no physical hardware) vs Programmer (stand alone)
;                       vs Debugger (ICD functionality)
;------------------------------------------------------------------------------
; Functioning: We first load 0Fh into the working register (WREG) and then from
; and it and then into PORTA. Does it work? Why?
;
; Notes:
; 1. Two different but equivalent ways of specifying hex numbers in code
;      80h (for any number starting with a number) = 0x80 (equivalent)
;      0F80h (if the number starts with a letter) = 0xf80 (equivalent)
;      For WATCH window: use 0xF80
;
; 2. Directives
;       Help Contents > Language Tools > MPASMX Toolchain > MPASM Assembler > Directives
;       Read through the information in this help file to familiarise yourself
;       with the nature and use of directives. Identify the directives in the
;       code below and look up their typical use in the help files.
; -----------------------------------------------------------------------------

title         "Our first Assembler program"
list          P=PIC18F45K22 ; processor type - include in your test & exam
; code so we can see you selected the correct
; device
#include    "p18f45K22.inc
; -------------
; PROGRAM START
; -------------
;
org         0h     ; startup address = 0000h

start     movlw            0xFF         ; move 11111111b to W register
movwf         PORTA        ; move W to port A
movlw         0x00         ; move 00000000b to W register
movwf         PORTA        ; move W to port A
BRA        delay

delay        equ  0x0F

again    nop        ;1 Instruction cycle each
nop
nop
nop

decfsz    delay, F, A

BRA    start
BRA    again        ;2 Intruction cycles

end
Mod edit: code tags

Last edited by a moderator:

specs365

Joined Mar 14, 2019
29
I hope the above is readable enough. AAC kind of Wrecked the code formatting

specs365

Joined Mar 14, 2019
29
Code:
        title         "Our first Assembler program"
list          P=PIC18F45K22 ; processor type - include in your test & exam
; code so we can see you selected the correct
; device
#include    "p18f45K22.inc"

;
; -------------
; PROGRAM START
; -------------
;
org         0h     ; startup address = 0000h

start     movlw            0xFF         ; move 11111111b to W register
movwf         PORTA        ; move W to port A
movlw         0x00         ; move 00000000b to W register
movwf         PORTA        ; move W to port A
BRA        delay

delay        equ  0x0F

again        nop        ;1 Instruction cycle each
nop
nop
nop

decfsz    delay, F, A

BRA    start
BRA    again        ;2 Intruction cycles

end

Ian Rogers

Joined Dec 12, 2012
774
I hope the above is readable enough. AAC kind of Wrecked the code formatting
On your reply toolbar is a "plus" symbol..Click that and "insert code tags" then paste your code.

Whoops too late..

Ian Rogers

Joined Dec 12, 2012
774
The loop will be 255.. "decfsz" is analysed after the event so 0 become 255 once this counts down F = 0 then the loop breaks. However... I just noticed that F is never initialized so the first loop could be anything.

JohnInTX

Joined Jun 26, 2012
4,072
There is another bug. Line 30 says
BRA delay

But 'delay' here is intended to be an address in RAM, not a label in the code. It would assemble as:
BRA 000Fh
which is not what you want.

FWIW, in this case, you would get a lucky error 12 from MPASM because the target address of that BRA is not word aligned i.e. an even number. But if 'delay' were an even number, the assembler would happily use that and you'd have some debugging to do.

Have fun learning!

jpanhalt

Joined Jan 18, 2008
9,405
Code:
start
movlw         0xFF         ; move 11111111b to W register
movwf         PORTA        ; move W to port A
movlw         0x00         ; move 00000000b to W register
movwf         PORTA        ; move W to port A
BRA           again        ; NOTE

delay        equ  ox0F               ;0x2F

again        nop        ;1 Instruction cycle each
nop
nop
nop

decfsz    delay,F

BRA    start
BRA    again        ;2 Intruction cycles

end
Had to make a few changes to run on a 16F1829. That code does compile and simulates, but doesn't do what you may thing it does. Line 9 had to be changed as that simply specifies a RAM location. 0x0F is not valid on the 16F. As Ian points out, delay is not initialized, so it can start with any value, go to zero, and wrap around.

I suggest listing your "equates" earlier in the code and not inline.

The "bra delay" just sits at the spot and does noting, because there are no instructions at that RAM location. That is why it was changed to "bra again."

PS: Sorry for all the edits, I accidentally hit the Enter key and posted the code before adding any comments.
@JohnInTX
Sorry to duplicate you. I started simulation, then writing long before you posted, then got distracted trying to fix the error in posting the code with no comment.

Last edited:

JohnInTX

Joined Jun 26, 2012
4,072
@jpanhalt No worries!

For @specs365
Your code does not initialize PORTA. On any PIC, you have to do some setup on the ports to make them work. Section 10.0 I/O ports in the datasheet details what you need to do there. You need to set the direction of the pins (input or output) using the TRIS register and also make the pins digital (some are analog after a RESET) using ANSELA. Init the ports once before entering your main loop.

The ,F and ,A modifiers to decfsz and others are covered in 25.1 Standard Instruction Set.
,F means that the result of the operation - in this case decrementing the register called 'delay' - is put back into the register which is what you want. The alternative is ,W which puts the result of the decrement in WREG. Not what you want here but look at movf for a good example of using ,W.
,A means that the register is in the Access RAM. Access RAM is always accessable so for now it's a good, easy place to put things. If you look at Figure 5-5 in the datasheet, you'll see that most of the RAM in this chip is in banks. If the 'delay' register was in one of those, you would have to specifically set the bank select register (BSR) to point at that bank before using that instruction. I'm sure your instructor will cover all of that as you go along.

specs365

Joined Mar 14, 2019
29
Thanks everyone,will do some more reading in the datasheet and see if I can figure it out

BobaMosfet

Joined Jul 1, 2009
1,106
Hi everyone, I understand this is a very basic question, but I'm still very new to assembly. I would just basically like to understand what the the following means:
=> The F and A after the decfsz command.
=> how do I know how many time the loop will execute (Probably something to do with the above question).

Here is my code. I'm just trying to flash some LEDs with a period of 1s

P.S. I'm not really sure if the decfsz command is used correctly.
Code:
; -----------------------------------------------------------------------------
; EMK310
; Example code 1.1
; Basic assembler program structure
; Lecturer: Prof T Hanekom
; Date of last revision: February 2016
;------------------------------------------------------------------------------
; SIMULATION, i.e. use SIMULATOR
; Check list:     1*. Simulation (no physical hardware) vs Programmer (stand alone)
;                       vs Debugger (ICD functionality)
;------------------------------------------------------------------------------
; Functioning: We first load 0Fh into the working register (WREG) and then from
; and it and then into PORTA. Does it work? Why?
;
; Notes:
; 1. Two different but equivalent ways of specifying hex numbers in code
;      80h (for any number starting with a number) = 0x80 (equivalent)
;      0F80h (if the number starts with a letter) = 0xf80 (equivalent)
;      For WATCH window: use 0xF80
;
; 2. Directives
;       Help Contents > Language Tools > MPASMX Toolchain > MPASM Assembler > Directives
;       Read through the information in this help file to familiarise yourself
;       with the nature and use of directives. Identify the directives in the
;       code below and look up their typical use in the help files.
; -----------------------------------------------------------------------------

title         "Our first Assembler program"
list          P=PIC18F45K22 ; processor type - include in your test & exam
; code so we can see you selected the correct
; device
#include    "p18f45K22.inc
; -------------
; PROGRAM START
; -------------
;
org         0h     ; startup address = 0000h

start     movlw            0xFF         ; move 11111111b to W register
movwf         PORTA        ; move W to port A
movlw         0x00         ; move 00000000b to W register
movwf         PORTA        ; move W to port A
BRA        delay

delay        equ  0x0F

again    nop        ;1 Instruction cycle each
nop
nop
nop

decfsz    delay, F, A

BRA    start
BRA    again        ;2 Intruction cycles

end
Mod edit: code tags
Since you're interested in assembly language, let's help you grasp the jargon. An assembly language instruction is called a 'mnemonic' (you can pronounce that 'knee-monic' or 'new-monic' as you prefer- but probably somewhere in between those two is what you're striving for). Each assembly instruction is spelled in a way to describe what it is. 'bra' = branch. 'decfsz' = decrement the file, skip if zero.

You need to look at a reference like this to wrap your head around what you're doing. Assembly language doesn't do much per instruction, but it executes so quickly it can do more than anything else.

http://users.tpg.com.au/users/talking/explaining_instruction_set.html

A loop works in assembly just like any other. You compare some value (usually to zero because that's the only value you know that doesn't have to be declared), and then either keep executing, or branch elsewhere.

Just bear in mind that in assembly language, you have to do everything- nothing is done for you. You are responsible for everything (setup, execution, tear down, managing memory, your registers, stack, frames, etc). But that also gives you the most power.

Last edited: