HSG

Aktuelle Seite: HSG/Fächer/Informatik/ MSR/PIC

Experimente mit den Flags

Das folgende kleine Programm sollte nicht wirklich in den PIC geladen werden, sondern mit Hilfe des Debuggers bearbeitet werden. Es soll die Bedeutung und Wirkung der Flags bei arithmetischen Operationen zeigen. Bei der Operation 7+11 wird das Digit-Carry gesetzt, warum? Wann wird das Carry-Flag gesetzt, wann das Zero-Flag? Zur Klärung dieser Fragen soll das Programm variiert werden. Das Original-Handbuch erläutert das STATUS-Register auf Seite 22. Eine prima "Lesson" zum Thema ist bei John McDonoughs PIC Elmer 160 Course Lessons zu finden.

        processor   pic16f877a
        #include    p16f877a.inc
        __config    _HS_OSC & _WDT_OFF & _PWRTE_ON

    ; Variablen
S1      equ         0x20            ; 1.Summand
S2      equ         0x21            ; 2.Summand

        org         0x00

reset   clrf        STATUS
        movlw       0x00
        movwf       PCLATH
        goto        main

        org         0x10

main
        movlw       d'7'
        movwf       S1
        movlw       d'11'
        movwf       S2

        bcf         STATUS,C        ; Carry-Flag zurücksetzen
        bcf         STATUS,DC       ; Digit-Carry-Flag zurücksetzen
        bcf         STATUS,Z        ; Zero-Flag zurücksetzen
        movfw       S1
        addwf       S2,f

loop    goto        loop

        end

Wer nicht den Simulator benutzen will, kann sich durch folgenden Code das STATUS-Register und damit die Flags auch auf PortB ausgeben lassen:

; Port-Setup
        bsf         STATUS,5        ; wechsle zu Bank1
        movlw       b'00000000'     ; setze Port B, Bit 0-7
        movwf       TRISB           ; als Ausgang
        bcf         STATUS,5        ; wieder in Bank 0 wechseln
; STATUS auf PortB ausgeben
        movfw       STATUS
        movwf       PORTB

16-Bit-Addition

16-Bit-Subtraktion

Multiplikation mit 2, Division durch 2

        bcf         STATUS,C  ; Carry-Flag löschen
        rlf         y,1
        bcf         STATUS,C  ; Carry-Flag löschen
        rrf         x,1

Multiplikation

Ein passender Algorithmus ist die sogenannte ägyptische Bauern-Multiplikation .

# -*- coding: iso-8859-1 -*-
# Autor: mk, 29.1.09

x = 13
y = 17
p = 0

while x > 0:
    if x%2 == 1:
        p = p + y
    y = y*2
    x = x/2

print p

erstes Assemblerprogramm

        processor   pic16f877a
        #include    p16f877a.inc
        __config    _HS_OSC & _WDT_OFF & _PWRTE_ON

    ; Variablen
x       equ         0x20            ; 1.Faktor
y       equ         0x21            ; 2.Faktor
p       equ         0x22            ; Produkt

        org         0x00

reset   clrf        STATUS
        movlw       0x00
        movwf       PCLATH
        goto        main

        org         0x10

main
        movlw       d'13'
        movwf       x
        movlw       d'17'
        movwf       y
        movlw       0x0
        movwf       p

sb      movf        x,1
        btfsc       STATUS,Z  ; x = 0?
        goto        se        ; x = 0
        btfss       x,0       ; x ungerade?
        goto        notaddy   ; x gerade
        movf        p
        addwf       y,0
        movwf       p
notaddy bcf         STATUS,C  ; Carry-Flag löschen
        rlf         y,1
        bcf         STATUS,C  ; Carry-Flag löschen
        rrf         x,1
        goto        sb
se

loop    goto        loop

        end

Division

Algorithmus in Python
# -*- coding: iso-8859-1 -*-
# Autor: mk, 9.6.09

x = 101
y = 23

q = 0
r = x
while r-y >= 0:
    r = r-y
    q = q+1

print x,'div',y,'=',q
print x,'mod',y,'=',r
Algorithmus in Assembler
        processor   pic16f877a
        #include    p16f877a.inc
        __config    _HS_OSC & _WDT_OFF & _PWRTE_ON

        ; Variablen
x       equ         0x20
y       equ         0x21
q       equ         0x22
r       equ         0x23

        org         0x00

reset:
        clrf        STATUS
        movlw       0x00
        movwf       PCLATH
        goto        main

        org         0x10
main:
        ; Eingaben
        movlw       d'101'
        movwf       x
        movlw       d'23'
        movwf       y
        ; Division
        call divmod
        ; Dauerschleife
loop:
        goto        loop

; --------------------------------------------
divmod:
        movlw       d'0'            ; q -> 0
        movwf       q
        movf        x,0             ; x -> r
        movwf       r
        bsf         STATUS,C        ; Carry-Flag setzen
dmloop:
        movf        y,0             ; y -> w
        subwf       r,0             ; r-w -> w
        btfsc       STATUS,C        ; Carry-Flag wird bei Unterlauf gelöscht
        goto        dmweiter
        goto        dmunterlauf
dmweiter:
        movf        y,0             ; y -> w
        subwf       r,1             ; r-w -> r
        incf        q               ; q+1 -> q
        goto        dmloop
dmunterlauf:
        return
; --------------------------------------------

        end

Links