Autor Beitrag
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mi 25.11.09 19:33 
Hallo!

Ich hab mir gedacht, ich könnte mich mal ein wenig mit Assembler beschäftigen. Deshalb hab ich angefangen, folgendes zu lesen: de.wikibooks.org/wik...ssor)-Programmierung

Ich bin jetzt in etwa hier: de.wikibooks.org/wik...te_Assemblerprogramm (sehr weit :lol: )

Dort steht:
Zitat:
Mit dem mov Befehl wird der zweite Operand in den ersten Operanden kopiert. Der erste Operand wird auch als Zieloperand, der zweite als Quelloperand bezeichnet. Beide Operanden müssen die gleiche Größe haben. Wenn der erste Operand beispielsweise die Größe von zwei Byte besitzt, muss auch der zweite Operand die Größe von zwei Byte besitzen.

Es ist nicht erlaubt, als Operanden das IP-Register zu benutzen. Wir werden später mit Sprungbefehlen noch eine indirekte Möglichkeit kennen lernen, dieses Register zu manipulieren.

Außerdem ist es nicht erlaubt, eine Speicherstelle in eine andere Speicherstelle zu kopieren. Diese Regel gilt für alle Assemblerbefehle mit zwei Operanden: Es dürfen niemals beide Operanden eine Speicherstelle ansprechen. Beim mov -Befehl hat dies zur Folge, dass, wenn eine Speicherstelle in eine zweite Speicherstelle kopiert werden soll, dies über ein Register erfolgen muss. Beispielsweise wird mit den zwei folgenden Befehlen der Inhalt von der Speicherstelle 0110h in die Speicherstelle 0112h kopiert:


Meiner Meinung nach ist das ein Widerspruch. Was ist nun damit gemeint, bzw. was ist mit "Speicherstelle" gemeint? Ein Register, ein Byte, ein Segment, eine Adresse?

Ich verstehe da irgendwie gerade nur Bahnhof. Insbesondere habe ich ja nicht vor, ein komplettes Programm in Assembler zu schreiben. Es geht mir hauptsächlich um den in Delphi eingebetteten Assembler. Wie soll ich denn dann mit Adressen umgehen? Die können doch jedes Mal anders sein!


Moderiert von user profile iconNarses: Topic aus Off Topic verschoben am Sa 19.12.2009 um 19:19
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Mi 25.11.09 19:39 
bei dem in delphi-eingebettetem assembler benutzt du keine adressen, sondern einfach die Variablennamen aus delphi.
Du kannst halt nicht schreiben
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var a, b: cardinal;
  begin
    asm
      mov a, b
    end;
  end;


sondern musst schreiben
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var a, b: cardinal;
  begin
    asm
      mov eax, b;
      mov a, eax;
    end;
  end;

Es darf halt entweder vom Ram ins Register oder vom Register ins ram, aber nie von Ram zu Ram...

Edit: Ich war schneller...


Zuletzt bearbeitet von Boldar am Mi 25.11.09 19:50, insgesamt 1-mal bearbeitet
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Mi 25.11.09 19:42 
Du kannst nicht von einer Adresse Daten direkt in eine andere Adresse kopieren sondern musst einen Umweg über den Stack bzw. ein Register machen

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
  mov dword ptr [$12345678], dword ptr [$87654321// geht nicht

  mov eax, dword ptr [$87654321]
  mov dword ptr [$12345678], eax  // geht

  push dword ptr [$87654321// geht
  pop dword ptr [$12345678]


also nur ein ptr. (wenn man jetzt wieder genau ist, dann ist das push sowas ähnliches, wenn esp auf die zieladresse zeigt)

_________________
wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
Jakob_Ullmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mi 25.11.09 19:58 
Vielen Dank euch beiden! Aber einwas wäre noch interessant: Geht denn dann Register nach Register, z. B. mov eax, edx?

uall@ogc: Deinen Code verstehe ich nicht, aber das ist hoffentlich auch noch nicht so schlimm. Was dword und ptr bedeuten, werde ich ja hoffentlich demnächst lernen.
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Mi 25.11.09 19:59 
user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Vielen Dank euch beiden! Aber einwas wäre noch interessant: Geht denn dann Register nach Register, z. B. mov eax, edx?

uall@ogc: Deinen Code verstehe ich nicht, aber das ist hoffentlich auch noch nicht so schlimm. Was dword und ptr bedeuten, werde ich ja hoffentlich demnächst lernen.

Register nach Register geht auch.
dword ist in dem fall eine Größenangabe, also dass die variable ein dword ist.
Ptr und die [] bedeuten zusätzlich, dass es sich um einen Pointer auf einen DWORD handelt, also sind die Zahlen in den Klammern die Adressen.
Jakob_Ullmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mi 25.11.09 22:05 
Danke, das war ebenfalls halbwegs verständlich. Den Rest kriege ich hoffentlich irgendwie gebacken...
Jakob_Ullmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Sa 19.12.09 20:14 
Ich glaube, es ist doch noch nicht alles klar. Und zwar stand ich letztens mit der Aufgabe konfrontiert, zwei Zeichen in einem String zu vertauschen. Mit Delphi in wenigen Sekunden erledigt. Aber irgendwie schien mir das zu langweilig und ich wollte mal ausprobieren, ob ich es auch in Assembler gebacken kriege. Ich habe also folgendes probiert:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function Swap(s: string; i: Integer): string// vertauschen des i. und (i + 1). Zeichens
var
  a: char;
begin
  asm
    mov eax, s[i]
    mov a, eax
    mov eax, s[i + 1]
    mov s[i], eax
    mov eax, a
    mov s[i + 1], eax
  end;
  Result := s;
end;


Ich hätte höchstens erwartet, dass der Code nicht das macht, was er soll, aber Delphi gibt ja gleich mal Compilerfehler aus (ungültige Registeroperation). Jede Speicherstelle in jeder Zeile wird rot unterkringelt. :wink:

Warum ist das so falsch und wie müsste es richtig heißen?
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 19.12.09 20:58 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure Swap(var s: string; i: Integer); // vertauschen des i. und (i + 1). Zeichens
asm
    test eax, eax
    jz @@e

    xchg cl, byte ptr[eax+edx]
    xchg cl, byte ptr[eax+edx+1]
    xchg cl, byte ptr[eax+edx]
@@e:
end;


Nicht mit Compiler getestet, dürfte aber ;-) Problem ist bei Strings die Referenzzählung. Die müsste man für ASM nämlich selber machen ... Außerdem beachten, dass ich ohne Stackframe arbeite.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Jakob_Ullmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mo 21.12.09 17:05 
Zitat:
Nicht mit Compiler getestet, dürfte aber ;-)

Ich habe auch gerade keinen Delphi-Compiler zur Hand, aber wenn du sagst, das geht, vertraue ich dir einfach mal.

Verstehe ich nicht. Muss man das so kompliziert machen oder geht das auch einfacher?

Warum sollte das funktionieren? Dort kommt doch nirgends auch nur einmal s oder i vor. Hat das was mit dem jz @@e zu tun?

Was mir gerade einfällt:
Gibt es eigentlich eine Möglichkeit (bzw. ich gehe davon aus, dass es eine gibt :wink: ), sich den von Delphi erzeugten Assemblercode anzusehen? Würde mich mal interessieren, wie Delphi den Code umsetzt (wäre sicher auch hilfreich).
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 21.12.09 17:32 
user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
Nicht mit Compiler getestet, dürfte aber ;-)

Ich habe auch gerade keinen Delphi-Compiler zur Hand, aber wenn du sagst, das geht, vertraue ich dir einfach mal.

Wenn ich schreibe "nicht getestet", dann heißt das genau das :P

user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Verstehe ich nicht. Muss man das so kompliziert machen oder geht das auch einfacher?

Das ist schon die einfachste Variante ... Man muss das mit dem XCHG nur mal eben per Hand durchexerzieren, dann sieht man, auch warum ;-)

user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Warum sollte das funktionieren? Dort kommt doch nirgends auch nur einmal s oder i vor.

Ich nutze die Register-Vorbelegung, die Delphi intern nutzt direkt. Zuordnung der Register ist immer EAX, EDX, ECX für die ersten drei Parameter, danach Stack. Wenn man auf die Parameternamen zugreift, dann baut Delphi da manchmal dermaßen merkwürdige Stackframes, da verzichte ich liebend gerne drauf.

user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Hat das was mit dem jz @@e zu tun?

Das JZ @@e prüft nur, ob überhaupt ein String übergeben wurde. Der Vollständigkeit halber müsste man eigentlich noch eine Prüfung des Indizes machen, aber die hab ich mir mal gespart für das Beispiel.

user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Was mir gerade einfällt: Gibt es eigentlich eine Möglichkeit (bzw. ich gehe davon aus, dass es eine gibt :wink: ), sich den von Delphi erzeugten Assemblercode anzusehen? Würde mich mal interessieren, wie Delphi den Code umsetzt (wäre sicher auch hilfreich).

Breakpoint setzen, CPU-Fenster öffnen.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Jakob_Ullmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mo 21.12.09 18:52 
Cool, danke!

EDIT: OK, mir ist doch noch was aufgefallen. Du schreibst test eax, eax. Was macht das test nun wieder? Oder gehört das mit dem jz @@e irgendwie zusammen? Ist das Absicht oder ein Fehler, dass beide Argumente eax sind?
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 21.12.09 19:16 
user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Cool, danke!

EDIT: OK, mir ist doch noch was aufgefallen. Du schreibst test eax, eax. Was macht das test nun wieder? Oder gehört das mit dem jz @@e irgendwie zusammen? Ist das Absicht oder ein Fehler, dass beide Argumente eax sind?

Ja, die beiden Zeilen gehören zusammen. Wird das etwa aus der visuellen Gliederung nicht klar ;-)???

TEST verknüpft die beiden argumente bitweise mit UND und schreibt das Ergebnis des Vergleichs in die CPU-Flags. Von dort frag ich das Ergebnis mit JZ ab ...

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Jakob_Ullmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mo 21.12.09 20:32 
Danke!