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 ------------------------
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.
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.
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.
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.)
Was nuetzt ihm die Grammatik wenn er die Rechtschreibung nicht kennt.
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
folgender c code
1 | uint16_t Add2(uint16_t v1,v2) |
2 | {
|
3 | return v1 + v2; |
4 | }
|
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.
1 | public Add2 |
2 | Add2 PROC near |
3 | push bp ; prolog |
4 | mov bp,sp |
5 | |
6 | mov bx,[bp+6]; erster parameter |
7 | mov ax,[bp+8]; zweiter parameter |
8 | add ax,bx ; ergebnis zurück in AX |
9 | |
10 | pop bp ; epilog |
11 | RET 4 |
12 | Add2 ENDP |
@TO wie du siehst helfen Kommentare ungemein
:
Bearbeitet durch User
> 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).
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?
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.
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?
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.
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.
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)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.