mikrocontroller.net

Forum: PC Hard- und Software ax-Wert übergeben an andere Routine mit bx


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Peter B. (funkheld)


Bewertung
0 lesenswert
nicht lesenswert
Hallo, guten Tag.
Wie kann man bitte einen Wert an eine andere Routine übergeben.

In add1 wird ein Wert an ax übergeben.
In Add2  wird wird ein Wert an bx übergeben und ax und bx werden 
addiert.
Und den Wert von Add2 möchte ich dann nutzen.

Wie kann das bitte funktionieren?

Danke.

--------------------------
.model medium, basic
.stack 200h
.386
.code

public Add1
Add1 proc
   push bp
   mov  bp, sp
   mov  ax, [bp+6]
   pop  bp
   ret  2
Add1 endp

public Add2
Add2   PROC
   push bp
   mov bp,sp
   mov bx,[bp+6]
   pop bp

   add ax,bx

   RET 2
Add2  ENDP

end
------------------------

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Bewertung
0 lesenswert
nicht lesenswert
Hä?

Welchen Wert von add2?

Den Kram hast Du doch nie selbst geschrieben... die Funktionen machen so 
überhaupt keinen Sinn, zumindest erkenne ich den aus den Schnipseln 
nicht. Was soll das Gewurstel mit dem Stack?

add2 zerstört jedenfalls erstmal den Inhalt von AX und BX, AX evtl. 
gewollt, BX wird nicht gesichert.

von Programmierer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kann irgendwer mal Mitleid haben und dem Kerl einen Haufen 
x86-Assembler-Bücher schicken... Ist ja nicht mit anzusehen wie er sich 
jeden Fitzel einzeln erfragt.

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Bewertung
0 lesenswert
nicht lesenswert
Bei ADD AX,BX wird AX mit dem Ergebnis überschrieben.

Wenn man die Summanden in AX und BX behalten möchte, muß man etwas mehr 
Aufwand betreiben. Bspw. sowas wie

MOV AX, summand1
MOV BX, summand2

MOV DX, AX
ADD DX, BX

Danach hat man das Ergebnis in DX, AX und BX bleiben erhalten.

Und Vorsicht, wenn die Summe größer als 65535 ist, läuft DX über bzw. 
das höchstwertige Bit landet im Übertragsflag.

von rbx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Peter B. schrieb:
> Und den Wert von Add2 möchte ich dann nutzen

Schreib doch einfach, in welcher Weise genau und unter welchen genauen 
Umständen, eventuell gibt es dann auch genauere Antworten.

Schmunzeln kann ich mir hier nicht verkneifen, weil die Frage ein wenig 
an Haskell erinnert, und da die Frage nach Monaden heraufbeschwört, die 
für sich nicht so einfach zu beantworten wäre.
(Da würde ich aber schreiben: einfach (erstmal) die (dazu) gängige 
Grammatik auswendig lernen.)

von oerks (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Was nuetzt ihm die Grammatik wenn er die Rechtschreibung nicht kennt.

von Thomas Z. (usbman)


Bewertung
0 lesenswert
nicht lesenswert
Ben B. schrieb:
> Den Kram hast Du doch nie selbst geschrieben... die Funktionen machen so
> überhaupt keinen Sinn, zumindest erkenne ich den aus den Schnipseln
> nicht. Was soll das Gewurstel mit dem Stack?

natürlich hat er das nicht selbst geschrieben. Er hat ja den typischen 
Prolog/epilog eines compilers. ich würde behaupten Add1 sieht so aus
uint16_t Add1(uint16_t param) { return param; }

Bei Add2 ist AX undefinert weshalb er vermutlich einen Weg sucht AX zu 
laden

Da er aber nicht versteht wie die Parameterübergabe auf dem Stack 
funktioniert kommt dann halt so ein sinloses Codeschipsel.

.386 ist ja nur ein weiters Zeichen dass er nicht weiss was er macht.

Thomas

von oerks (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> .386

Wenn er erst .586 entdeckt wirds lustig.

von Thomas Z. (usbman)


Bewertung
1 lesenswert
nicht lesenswert
folgender c code
uint16_t Add2(uint16_t v1,v2)
{
   return v1 + v2;
}

entspricht in etwa diesem Assembler code. Immer unter der Vorraussetzung 
dass der compiler near code erzeugt. und die Funktion selbst die 
parameter vom stack holt.
public Add2
Add2   PROC near
   push bp      ; prolog
   mov bp,sp

   mov bx,[bp+6]; erster parameter
   mov ax,[bp+8]; zweiter parameter
   add ax,bx    ; ergebnis zurück in AX

   pop bp       ; epilog
   RET 4
Add2  ENDP

@TO wie du siehst helfen Kommentare ungemein

: Bearbeitet durch User
von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Bewertung
0 lesenswert
nicht lesenswert
> Bei Add2 ist AX undefinert weshalb er vermutlich
> einen Weg sucht AX zu laden
In Assembler ist nie irgendwas undefiniert, es ist höchstens "leer" bzw. 
enthält nicht das was man haben wollte oder erwartet hat.

Wenn man in seinem Beispiel beide Funktionen (Add1 und Add2) direkt 
nacheinaner ausführt, läd Add1 AX für Add2. Mega-umständlich, aber kann 
man machen (im Sinne von das würde so funktionieren).

von rbx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Man kann sich aber schon ein wenig darüber wundern, warum der 
abgeschriebene Code keinen Platz bzw. ( 
http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm ) 
keinen 16 Bit-int für das Ergebnis gelassen hat.

Erst recht, weil Addition ja noch geht, Multiplikation dagegen.. ;)

Was ich mich nämlich oft gefragt hatte, war - wie haben die das nur 
immer mit den 8-Bit-Kisten (oder Taschenrechnern) so hinbekommen?

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Bewertung
0 lesenswert
nicht lesenswert
Im Grunde sind das ähnliche Verfahren wie Du solche Aufgaben schriftlich 
lösen würdest. Da teilst Du die Aufgabe auch in mehrere kleine Teile und 
genau so macht es ein Computer auch.

Zwei 16-Bit-Werte kann der x86 auch problemlos multiplizieren, das 
Ergebnis landet dann in DX:AX wenn ich mich recht erinnere. Also in DX 
die oberen 16 Bit und in AX die unteren. Habe ich aber seeeeehr lange so 
nicht mehr gebraucht, also nagelt mich nicht darauf fest.

von Funkdepphasser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Programmierer schrieb:
> Kann irgendwer mal Mitleid haben und dem Kerl einen Haufen
> x86-Assembler-Bücher schicken... Ist ja nicht mit anzusehen wie er sich
> jeden Fitzel einzeln erfragt.

Peter B.Löd ist doch schon zu dämlich Google zu benutzen. Der fragt dann 
das Buch und es kommt keine Antowrt aus dem nicht-eingebauten 
Lautsprecher raus.
Wo ist eigentlich sein Arschabwischer cppbert geblieben?

von rbx (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Ben B. schrieb:
> also nagelt mich nicht darauf fest

passt schon, man kann auch mit AL/AH multiplizieren. Das schöne bei mul 
BX bzw. div BX (o.ä.) ist, dass bei beim Aufteilen der Rest im 
DX-Register landet.
Bevor man damit anfängt, muss unbedingt DX initialisiert werden!

https://www.tutorialspoint.com/assembly_programming/assembly_arithmetic_instructions.htm

Der TO/TE muss sich aber festlegen,

a)wieviel Schritte er mit seinem Stackzeiger gehen will bzw. muss.
b)welches Datenformat die Routine, die den berechneten Wert aufnehmen 
soll, haben sollte.

BP+6 hat in dieser Hinsicht wenig Auskunft über die Übergabeform - 
könnte man aber zur Übung als "Summe" missbrauchen.

Wenn man genau weiß, wo der Stackzeiger gerade hinzeigt, bzw. was man 
nicht überschreiben möchte, dann könnte ein push AX in der Routine 
reichen.

Lässt man den Stack weg, dann kann man einfach den Speicherbereich 
hinter dem Programm nutzen. Dazu muss man ausrechnen, wie groß das 
Programm wird, bzw. wo der Datenbereich anfangen kann.
D.h. man kann z.B. den Speicherzeigern erstmal Dummy-Namen geben.
Wenn man keine Lust zum Rechnen hat, dann kann man den Datenbereich 
extra weiter hinten anlegen, und die Schritte Alignmentfreundlich 
gestalten bzw. z.B. BX (irgendwo weiter hinten) + 10h oder BX + 100h 
oder von mir aus und wenn es Spaß macht, BX + Si und später die 
Feinabstimmung im Hexeditor machen.

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Bewertung
0 lesenswert
nicht lesenswert
Wie gesagt, das Gewurstel mit dem Stack verstehe ich nicht. Eigentlich 
probiert man in der Assembler-Programmierung auf maximale 
Geschwindigkeit zu optimieren, oder auf kleinste Codegröße.

XOR AX,AX ist z.B. kleiner als MOV AX,0

Zum Thema Geschwindigkeit: Das schnellste was da ist, sind die Register, 
also probiert man möglichst nur diese zu benutzen und jede Form von 
Speicherzugriffen zu vermeiden. In Zeiten von 64 Bit SSE/AVX stehen da 
auch richtig viele Register zur Verfügung, mit ordentlich Speicherplatz. 
Ansonsten  halt probieren, mit dem auszukommen, was da ist. In Assembler 
ist man an keine "Konventionen" gebunden, wenn ich z.B. ES oder DS 
gerade nicht brauche, kann man auch dort 16 Bit drin speichern. BP wird 
dafür sehr gerne genommen, oder SI/DI.

Oder versuchen, die zur Verfügung stehenden Features auch zu nutzen.

MOV ES:[DI],AX
ADD DI,2

macht z.B. das gleiche wie

STOSW

Bei Funktionen kann man sich den Umweg über den Stack sparen, solange 
Funktionen nicht rekursiv aufgerufen werden. Also z.B.

MOV AX,wert1
MOV BX,wert2
CALL (short) funktionsname
CMP AL,0 ;Rückgabewert, 0 für kein Fehler

Es macht auch Sinn, wenn die Funktionen ihre Rückgabewerte gleich in den 
passenden Registern zurückliefern. Beispielsweise

CALL (short) GetDataSize
CMP CX,0 ;Rückgabewert in CX passend für nachfolgende Schleifen

Naja kann man noch viel drüber schreiben. Leider werden wir wohl nie 
erfahren, was der TE eigentlich genau will.

von rbx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ben B. schrieb:
> Naja kann man noch viel drüber schreiben. Leider werden wir wohl nie
> erfahren, was der TE eigentlich genau will.

Zumindest ein wenig Taschenlampenlicht mit schwacher Batterie drauf 
werfen geht noch, ohne den Compi zu wechseln, oder auf den Dachboden 
gehen zu müssen:

https://forum.nasm.us/index.php?topic=2548.0
(Addierbeispiel mit zwei ints und dem Watcom Compiler und Nasm)

Dann noch die OpenWC userguide der Teil mit dem Hinweis auf Assembler
bzw. 16-bit Topics:
http://www.openwatcom.org/doc.php (cguide.pdf oben)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.