Forum: Mikrocontroller und Digitale Elektronik verstehe den ARM Code nicht


von Walter (Gast)


Lesenswert?

ich steh hier irgendwie auf dem Schlauch
ich übersetze mit dem arm-gcc den folgenden Code

char bitnr=24;
for ( ; bitnr>=0; )
{
  ....
  bitnr--;
}

die Schleife soll also 25x durchlaufen werden, wird aber mind 1x mehr 
durchlaufen (habe leider keinen Debugger/Simulator)

das Listing dazu:
1005 064e 631E         sub  r3, r4, #1
 1006 0650 1B06         lsl  r3, r3, #24
 1007 0652 1C0E         lsr  r4, r3, #24
 1008 0654 0723         mov  r3, #7
 1009 0656 1C42         tst  r4, r3
 1010 0658 D2D1         bne  .L192

tst ist doch ein AND ohne das Ergebnis zu speichern?
was soll das AND mit 7 dann bewirken?

Das Geshifte macht auf mich den Eindruck als ob er bitnr als unsigned 
betrachtet?

von (prx) A. K. (prx)


Lesenswert?

Das Geshifte zeigt, dass Datentypen unter 32 Bits bei ARMs in Registern 
ziemlich ineffizient sein können. Besser int oder portabel int_fast8_t 
verwenden.

Der Konstante 7 lässt sich möglicherweise nur zusammen mit dem übrigen 
Quell/ASM-Code interpretieren.

NB: "char" ist nicht zwingend mit Vorzeichen. Darf auch ohne sein, und 
rate mal was dann rauskommt.

von 123 (Gast)


Lesenswert?

so wenn der ein char als unsigned betrachtet, dann kann das ding nie 
kleiner als 0 werden und du hast somit eine schöne endlosschleife. und 
damit macht das ding mehr als die von dir gewünschten 25 durchläufe.

du weist das arm befehle von statusflägs abhängig gemacht werden können?

tst beeinflusst irgend welche statusflags, die dann den bne beeinflussen 
soll er jetzt springen oder nicht

von Walter (Gast)


Lesenswert?

A. K. schrieb:
> Der Konstante 7 lässt sich möglicherweise nur zusammen mit dem übrigen
> Quell/ASM-Code interpretieren.
stimmt, da ist noch mehr

>
> NB: "char" ist nicht zwingend mit Vorzeichen. Darf auch ohne sein, und
> rate mal was dann rauskommt.
tja, wieder was gelernt, ich dachte char ist immer signed

von Andy K. (notandy)


Lesenswert?

> tja, wieder was gelernt, ich dachte char ist immer signed

arm-gcc interpretiert char aus performancegründen immer als unsigned 
char, ganz im gegensatz zum x86-gcc. Sehr lustig bei scheinbar portablen 
code.

von Ralph (Gast)


Lesenswert?

Walter schrieb:
> char bitnr=24;
> for ( ; bitnr>=0; )
> {
>   ....
>   bitnr--;
> }
>
> die Schleife soll also 25x durchlaufen werden, wird aber mind 1x mehr
> durchlaufen (habe leider keinen Debugger/Simulator)

Na dein letzter gewollter Durchlauf ist ja bei bitnr = 0 ;
Dann machst du wieder ein bitnr -1.
Demzufolge ist bitnr = 255.
Damit ist die Bedingungen bitnr >= erfüllt und es geht munter weiter.

Um hier eine sichere Abbruchbedingung zu haben die auch bei 
unterschiedlicher Interpretation von char ( unsigned  - signed) 
funktioniert mach es etwas anderes.
 char bitnr=25;
 for ( ; bitnr>0; )
 {
   ....
   bitnr--;
 }
Dann erfolgt der letzte durchlauf bei bitnr = 1 ==> bitnr --  führt zu 
bitnr = 0 ==> saubere Abbruchbedingung

Walter schrieb:
> Das Geshifte macht auf mich den Eindruck als ob er bitnr als unsigned
> betrachtet?

Was denn auch sonst; "char" indiziert das ein Text Zeichen (ASCII) 
gemeint ist. ASCII Code ist immer Positiv , also unsigned.

Wenn ein signed wert benötigt wird sollte man auch explizit den 
entsprechenden Typ verwenden.

von (prx) A. K. (prx)


Lesenswert?

Ralph schrieb:
> Was denn auch sonst; "char" indiziert das ein Text Zeichen (ASCII)
> gemeint ist. ASCII Code ist immer Positiv , also unsigned.

ASCII Code ist nur deshalb immer positiv, weil er bei 0x7F aufhört. Ob 
char mit oder ohne Vorzeichen ist, das hängt nicht vom codierten Zeichen 
ab. Mit solcher Logik kriegt man diesen Aspekt von C nicht zu fassen. 
Das wird nur klar, wenn man die Architektur der PDP-11 betrachtet und 
daraus eine Tradition macht.

Ob char mit oder ohne Vorzeichen ist, wird folglich vom ABI definiert, 
dem der Compiler folgt.

von Jürgen S. (starblue) Benutzerseite


Lesenswert?

Wie wär's, wenn du wenigstens mal den vollständigen Kode der Schleife 
postest, bevor wir hier weiterdiskutieren.

Dazu bitte den vollständigen Assemblerkode inklusive Label für den 
Sprung.

von Walter (Gast)


Lesenswert?

Ralph schrieb:
> Dann erfolgt der letzte durchlauf bei bitnr = 1 ==> bitnr --  führt zu
> bitnr = 0 ==> saubere Abbruchbedingung

schon klar, dann müsste ich mir aber für bitnr eine andere Bezeichnung 
ausdenken ...

Jürgen S. schrieb:
> Wie wär's, wenn du wenigstens mal den vollständigen Kode der Schleife
> postest, bevor wir hier weiterdiskutieren.

is ja schon geklärt, es war das signed/unsigned Problem

von Walter (Gast)


Lesenswert?

Ralph schrieb:
> Walter schrieb:
>> Das Geshifte macht auf mich den Eindruck als ob er bitnr als unsigned
>> betrachtet?
>
> Was denn auch sonst

na ja signed natürlich, bei allen Compiler mit denen ich bisher zu tun 
hatte, und das sind einige, war char signed ...

mit signed char kriegt man das ganze dann auch kompatibel

von Rolf Magnus (Gast)


Lesenswert?

Walter schrieb:
> Ralph schrieb:
>> Walter schrieb:
>>> Das Geshifte macht auf mich den Eindruck als ob er bitnr als unsigned
>>> betrachtet?
>>
>> Was denn auch sonst
>
> na ja signed natürlich, bei allen Compiler mit denen ich bisher zu tun
> hatte, und das sind einige, war char signed ...

Ist an sich auch konsitenter, da alle anderen integer-Typen auch signed 
sind, wenn nichts explizit davor steht. Nur kann man sich in C darauf 
leider nicht verlassen.

> mit signed char kriegt man das ganze dann auch kompatibel

Ja. Man muß nur einer einfachen Regel folgen: char nimmt man nur für 
Text. Sobald man damit rechnen will, es also als kleinen Integer 
verwenden, schreibt man grundsätzlich immer signed oder unsigned davor.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.