PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : If else in Assembler



Trexis5
27.09.2010, 17:08
Hi,

wie setzte ich den Basic Code in Assembler um?
Der Code sollte so schnell wie möglich ablaufen.



If G_erase = 1 Then
Gl_rstflag = 1
Else
Gl_rstflag = 0
End If


Danke

PicNick
27.09.2010, 17:15
Kommt sehr auf die Daten-Typen an (Byte , Word, etc.)
schau dich da mal um:
http://www.rn-wissen.de/index.php/Assembler_Einf%C3%BChrung_f%C3%BCr_Bascom-User#Verzweigen

Trexis5
27.09.2010, 17:52
Hi,

Danke.

das ist alles in Byte.

So geht es. Ist sogar etwas schneller.
Geht das vielleicht noch schneller? #-o



$asm
LDs R25, {G_erase} '
LDI R24, 1 ' R24 = 1

CP R25, R24
BREQ Label_1 ' Verzweigen nach "Ziel", wenn R25 = R24

LDI R22, 0 ' das machen wir (zum Beispiel), wenn R25 NICHT= r24 ist
RJMP Label_2 'wir müssen unbedingt springen, sonst laufen wir ja

Label_1:
LDI R22, 1 ' das machen wir (zum Beispiel), wenn R25 = r24 ist

Label_2:
sts {Gl_rstflag} , R22

$end Asm

Besserwessi
27.09.2010, 18:23
Das geht noch einiges schneller. Für den Vergleich mit Konstanten gibt es z.B. den Befehl CPI. Statt eine IF then else kann man es auch leich umschreiben auf nur eine Verzweigung, indem man erst ein register mit 0 läd, dann den Vergleich macht und ggf die 1 durch eine 0 ersetzt. Dann kann man den Registerinhalt zurückschreiben.
Da hier nur ein Befehl über sprungen wird kann man auch statt dem Sprung ein Skipbefehl genutzt werden.
Als Besonderheit gibt es dann noch den Befehl SPSE für ein ganz besonder kurze Lösung.
Also etwa so:

ldi R24 , 1
lds R25, Variable1
CPSE R24,R25
ldi R24,0
STS Varaible2, R24

Trexis5
27.09.2010, 19:42
Cool danke.
Das teste ich gleich mal.

Trexis5
27.09.2010, 19:59
Hi,

super, nur diese eine Funktion macht fast 0,6% aus.
Das hört sich nicht vielleicht nicht vile an, aber wenn ich alles austausche dann wird das GLCD immer schneller.
Das Programm ansich ist mir egal wie lange das dauert, das bekokmme ich auch nicht mit. Ob die Temperaturberechung 0.01sec. schneller ist als vorher spielt ja kene Rolle bei einer Wetterstation.
Aber die Anzeige sehe ich.

PicNick
28.09.2010, 09:05
Bei genauerer Betrachtung der Aufgabenstellung brauchst du gar kein "IF", sondern nur den "1"-er oder "0"-er von G-erase nach G_rstflag zu übertragen.



$asm
LDS R25, {G_erase}
ANDI R25, 1 ' alles ausser 1 wegmaskieren
STS {Gl_rstflag} , R25
' that's it
$end Asm

Trexis5
28.09.2010, 18:39
Cool. Danke.
Geht noch schneller.
Bald habe ich gar keinen Code mehr. ](*,)

Noch ne Frage

In Bascom gibt es den Befehl MOD.

Ich habe z.B. die Funktion Mod8 verwendet.
Ich habe das in dies hier verändert.
Stimmt das so?


$asm
lds R24, {Gl_x}
Mod8:
subi r24, 80
brcs rest8
subi r24, 80
brpl sub8
Rest8:
subi r24, -80
Sub8:
subi r24, 8
brpl sub8
subi r24, -8
Mod8_exit:
LDI R25, 7
!sub r25, r24

sts {Gl_bit} , R25
$end Asm

PicNick
28.09.2010, 19:39
Wenn du den 8-er Rest brauchst,


$asm
LDS R25, {Gl_x}
ANDI R25, 7 ' alles ausser 0-7 wegmaskieren
STS {Gl_bit} , R25
' that's it
$end Asm

Bei Werten, die keine 2-er Potenzen sind, musst du allerdings meist wirklich durch die Gegend dividieren

Besserwessi
28.09.2010, 20:00
Die Version mit dem ANDI für das orignal Problem ist nicht zu 100% das gleiche wie der original BASIC Code. Wenn da z.B. der Wert 3 vorkommt, macht der original Code daraus eine 0 die Version mit dem ANDI eine 1. Es gibt aber Fälle wo es so geht.

Trexis5
21.10.2010, 11:05
Hi,

ich habe noch was.
Wie setzte ich das um.
Das geht doch mit
in R16, PIND ; lies den Eingang von Port D
oder?
Aber wie geht das dann das .gl_bit gesetzt wird und die anderen Port's nicht überschrieben werden?




Gl_inp Alias Pina 'LCD data input
Gl_tris Alias Ddra 'LCD data redirection
Dim Gl_bit As Byte
Dim Gl_rstflag As Byte
Dim Gl_pix As Byte

Gl_tris = &B00000000 'Port input

Gl_read = Gl_inp 'laden

Gl_tris = &B11111111 'port output



If Gl_rstflag = 0 Then
Set Gl_read.gl_bit
Else
Reset Gl_read.gl_bit
End If
Gl_pix = Gl_read
end

PicNick
21.10.2010, 12:04
da gl_bit eine BitNUMMER von 0 - 7 ist, du aber für das setzen eine BitMASKE brauchst, musst du letztere erstmal durch links-shiften eines 1-ers (gl_bit mal) konstruieren. dann kannst du mit OR setzen.
oder Maske invertieren und mit AND löschen

ein Beispiel für das konvertieren findest du bei
http://www.rn-wissen.de/index.php/Bascom_Inside-Code#PULSEIN

Trexis5
21.10.2010, 12:33
$asm
.equ Gl_tris_asm = Ddra
$end Asm

lds R20,{Gl_bit}
!cbi Gl_tris_asm, 3 '; löscht das Bit 3 in DDRA



Das geht so.
Aber ich kann jetzt nicht die 3 durch die R20 ersetzen.

PicNick
21.10.2010, 16:02
LDS r24 , {Gl_bit}

L_0x00F6:
LDI r25,0x01 ' 1-er laden
AND r24,r24 ' gl_bit = 0 ?
BREQ L_0x0104 ' dann fertig
CLC ' clear carry
L_0x00FE:
ROL r25 ' rot left
DEC r24 ' bit-nr - 1
BRNE L_0x00FE ' fertig ?
L_0x0104:
'-------------------------------------------------------------------------
LDS r23, {gl_read }
OR r23, r24 ' bit setzen

'-------------------------------------------------------------------------
COM r24 ' invertieren
AND r23, r24 ' bit löschen

'-------------------------------------------------------------------------
STS { Gl_pix } , r23

Trexis5
21.10.2010, 17:58
Hi,
danke.
Ich habe es mal eingebaut, aber es geht nicht.



'-----------------------------
$asm
LDS r24, {Gl_bit}

L_0x00f6:
LDI r25,0x01 ' 1-er laden
!AND r24,r24 ' gl_bit = 0 ?
BREQ L_0x0104 ' dann fertig
CLC ' clear carry
L_0x00fe:
ROL r25 ' rot left
DEC r24 ' bit-nr - 1
BRNE L_0x00FE ' fertig ?
L_0x0104:
LDS r23, {gl_read}
COM r24 ' invertieren
$end Asm

If Gl_rstflag = 1 Then
!OR r23, r24 ' bit setzen
Else
!AND r23, r24 ' bit löschen
End If

!STS {Gl_pix}, r23
'-----------------------------------------------------


Was mache ich falsch.

PicNick
21.10.2010, 19:32
LDS r23, {gl_read}
$end Asm

If Gl_rstflag = 1 Then
!OR r23, r24 ' bit setzen
Else
COM r24 ' invertieren
!AND r23, r24 ' bit löschen
End If

!STS {Gl_pix}, r23

Trexis5
22.10.2010, 01:12
Hi,

sorry, aber es will nicht.



'-----------------------------
Gl_read = Gl_inp 'PIND 'Assign data
Gl_tris = &B11111111 'port output


$asm
LDS r24, {Gl_bit}

L_10x00f6:
LDI r25,0x01 ' 1-er laden
!AND r24,r24 ' gl_bit = 0 ?
BREQ L_10x0104 ' dann fertig
CLC ' clear carry
L_10x00fe:
ROL r25 ' rot left
DEC r24 ' bit-nr - 1
BRNE L_10x00FE ' fertig ?
L_10x0104:
LDS r23, {gl_read}
$end Asm


If Gl_rstflag = 1 Then
!OR r23, r24 ' bit setzen
Else
COM r24 ' invertieren
!AND r23, r24 ' bit löschen
End If

!STS {Gl_pix}, r23
'-------------------------------

PicNick
22.10.2010, 09:20
sry, waren fehler drin.

das hier jedenfalls hab ich getestet, das tut, wie es soll.


Gl_rstflag = 1 ' zum testen
Gl_bit = 3 ' zum testen

$asm
LDS r24, {Gl_bit}
L_10x00f6:
ldi r25, &H01
!AND r24,r24 ' gl_bit = 0 ?
BREQ L_10x0104 ' dann fertig
CLC ' clear carry
L_10x00fe:
ROL r25 ' rot left
DEC r24 ' bit-nr - 1
BRNE L_10x00FE ' fertig ?
L_10x0104:
LDS r23, {gl_read}
$end Asm


If Gl_rstflag = 1 Then
!OR r23, r25 ' bit setzen
Else
COM r25 ' invertieren
!AND r23, r25 ' bit löschen
End If

!STS {Gl_pix}, r23


Anm: sowas wie "ldi r25, 0x01" ignoriert Bascom ohne meldung
muss aber heissen (Bascom-Style)
"ldi r25, &H01"

Trexis5
22.10.2010, 19:17
Hi,

also sorry, es geht nicht.
Komisch es werden keine Linien angezeigt.
So wie jetzt geht es, sobald ich Bascom Code überspringe geht es nicht.




'----------------------------------
!sbi Glcd_controll,Gl_a0_asm 'CD high
'Gl_dat = Sys_mread
!lds R20, {Sys_mread_asm}
!out Gl_dat_asm, R20
!cbi Glcd_controll,Gl_wr_asm 'WR low
! nop
!sbi Glcd_controll,Gl_wr_asm 'WR high
!cbi Glcd_controll,Gl_a0_asm 'CMD low
'! nop
'Gl_tris = &B00000000 'Port input 'Make portd input
clr R20 '&B00000000'
!out Gl_tris_asm,R20


!sbi Glcd_controll,Gl_a0_asm 'Set A0 high
!cbi Glcd_controll,Gl_rd_asm 'RD low
ser R20 '&B11111111
! nop
! nop
! nop
! nop
! nop
'Gl_read = Gl_inp 'PIND 'Assign data
in R18,Gl_inp_asm
sts {Gl_read} , R18

!sbi Glcd_controll,Gl_rd_asm 'RD high
! nop
!cbi Glcd_controll,Gl_a0_asm 'CD low high
'Gl_tris = &B11111111 'port output
!out Gl_tris_asm, R20
'--------------------------------



If Gl_rstflag = 0 Then
Set Gl_read.gl_bit
Else
Reset Gl_read.gl_bit
End If
Gl_pix = Gl_read


Goto Jumptestasm
'-----------------------------

$asm
LDS r24, {Gl_bit}

L_10x00f6:
LDI r25, &H01 ' 1-er laden
!AND r24, r24 ' gl_bit = 0 ?
BREQ L_10x0104 ' dann fertig
CLC ' clear carry
L_10x00fe:
ROL r25 ' rot left
DEC r24 ' bit-nr - 1
BRNE L_10x00FE ' fertig ?
L_10x0104:
LDs R23, {gl_read}
$end Asm


If Gl_rstflag = 1 Then
!OR r23, r24 ' bit setzen
Else
COM r24 ' invertieren
!AND r23, r24 ' bit löschen
End If

!STS {Gl_pix}, r23
'-------------------------------
Jumptestasm:



!sbi Glcd_controll,Gl_a0_asm 'CD high
!lds R20, {Sys_cur_addr_asm}
!out Gl_dat_asm, R20
'Gl_dat = Sys_cur_addr 'CSRW cmd
!cbi Glcd_controll,Gl_wr_asm 'WR low
! Nop
!sbi Glcd_controll,Gl_wr_asm 'WR high
!cbi Glcd_controll,Gl_a0_asm 'CMD low
! nop

!lds R20, {Gl_addrlo}
!out Gl_dat_asm, R20
'Gl_dat = Gl_addrlo
!cbi Glcd_controll,Gl_wr_asm 'WR low
! nop
!sbi Glcd_controll,Gl_wr_asm 'WR high

!lds R20, {Gl_addrhi}
!out Gl_dat_asm, R20
'Gl_dat = Gl_addrhi
!cbi Glcd_controll,Gl_wr_asm 'WR low
! nop
!sbi Glcd_controll,Gl_wr_asm 'WR high

!sbi Glcd_controll,Gl_a0_asm 'CD high

!lds R20, {Sys_mwrite_asm}
!out Gl_dat_asm, R20
'Gl_dat = Sys_mwrite
!cbi Glcd_controll,Gl_wr_asm 'WR low
! nop
!sbi Glcd_controll,Gl_wr_asm 'WR high
!cbi Glcd_controll,Gl_a0_asm 'CMD low

!lds R20, {Gl_pix}
!out Gl_dat_asm, R20
'Gl_dat = Gl_pix
!cbi Glcd_controll,Gl_wr_asm 'WR low
! nop
!sbi Glcd_controll,Gl_wr_asm 'WR high

!lds R20, {Gl_rstflag}
clr R20

'Gl_rstflag = 0