crt_printf zerstört Programmroutine
-
Danke dir für die schnelle Antwort.
Allerdings habe ich noch ein paar Fragen:
1. Gibt es eine Liste mit allen Datentypen, die masm akzeptiert?
2. Wie kann ich einzelne Bytes per mov mit Offsets kopieren?
z.B:
meintext db "hallo", 0
meinbuchstabe byte 0mov meinbuchstabe, meintext+0 ;ersten buchstaben in das byte schreiben
mov meinbuchstabe, meintext+1 ;zweiten buchstaben in das byte schreibenLeider wird dies nicht akzeptiert. Wie lautet die richtige Syntax dazu?
-
1. masm kennt alle x86-spezifischen Datentype (z.B. DWORD,REAL4,REAL8,...)
2. byte in ein Register laden und anschließend an die Zieladresse schreibenmov al,meintext[0] mov meinbuchstabe,al
Das hat im übrigen nichts mit dem Syntax zu tun, sondern liegt an der x86-Archetektur, die immer nur eine Speicheroperanten pro Befehl erlaubt. (Ausnahmen push/pop)
-
Danke dir nochmal für die gute Antwort
Wenn man schonmal ein Forum findet, wo die Nutzer sogar aktiv bei "schwierigen" Fragen antworten muss ich das mal ausnutzenIch habe noch ein bisschen im Forum gestöbert und habe versucht eine Datei auszulesen.
Leider funktioniert die Readfile-Funktion nicht wirklich. OllyDbg stoppt immer bei der FileRead-Funktion und anschliessend krepiert das programm:;fenster.asm .386 .MODEL flat,stdcall option casemap:none INCLUDE \masm32\include\windows.inc INCLUDE \masm32\include\user32.inc INCLUDE \masm32\include\kernel32.inc INCLUDELIB \masm32\lib\user32.lib INCLUDELIB \masm32\lib\kernel32.lib includelib \masm32\lib\msvcrt.lib include \masm32\include\msvcrt.inc include \masm32\macros\ucmacros.asm .DATA filename db "meinetxt.txt", 0 zaehleranzeige db "Datei: %s", 13, 10, 0 dwZaehler dd 0 .DATA? ;uninitialisierte Daten filed HANDLE ? filesize dword ? allocatedmem HGLOBAL ? .CODE start: invoke CreateFile, addr filename, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL mov filed, eax ;HANDLE vom Rückgabewert abspeichern invoke GetFileSize, filed, NULL mov filesize, eax ;dateigrösse abspeichern invoke GlobalAlloc, NULL, filesize mov allocatedmem, eax invoke ReadFile, filed, allocatedmem, filesize, NULL, NULL ;=====> ;invoke crt_printf, zaehleranzeige, allocatedmem invoke CloseHandle, filed invoke GlobalFree, allocatedmem invoke ExitProcess, 0 END start
Ausserdem hätte ich noch eine Frage zu Pointer:
Was bewirkt das Macro "addr" und wo liegt der Unterschied zu Offset? Schließlich muss ich in C++, wenn ich einen C-String übergeben will, nicht &buffer schreiben.€dit: Gibt es einen äquivalenten Befehl zu char[100]? Ich möchte nur einen leeren Adressraum von 100 Bytes haben. Allerdings ist es sinnlos in diesem Fall GlobalMem zu benutzen, da ich diesen Buffer immer brauche.
-
RadFile schlägt fehl, da du eine ungültigen Zeiger übergibst (-> msdn). Der ADDR-Operator erlaubt es lokale variablen zu adressieren:
invoke myFunction,ADDR var
wird zu:
lea eax,var ; var ist dabei Irgendetwas wie z.B. [ebp-4] push eax call myFunction
Wenn du eine Statischen Puffer anlegen willst:
.data? puffer BYTE 100 dup (?) ; die Klammern unbedingt angeben (Syntax)
Hier mal wie ich es machen würde - die Sache ist (für mich) ziemlich trivial. Von daher würde ich hier die macros benutzen, die das MASM SDK mitliefert. Diese sind nichts weiter als WinAPI-wraper. Hilfe zu den macros findest du unter \masm32\help\hlhelp.chm (oder in macros.asm)
include \masm32\include\masm32rt.inc .code main proc LOCAL buffer[100]:BYTE ; loakel puffer (auf dem stack) LOCAL hFile:HANDLE LOCAL ccBuffer:DWORD LOCAL pBuffer:PCHAR LOCAL cbWritten:DWORD .if fopen("meinetxt.txt") != INVALID_HANDLE_VALUE mov hFile,eax mov ccBuffer,fsize(eax) ; Dateigröße .if eax mov pBuffer,alloc(eax) .if fread(hFile,pBuffer,ccBuffer) print "txt: '" mov edx,rv(GetStdHandle,STD_OUTPUT_HANDLE) invoke WriteConsole,edx,pBuffer,ccBuffer,ADDR cbWritten,0 print "'",13,10 .else print "unexpected behaviour",13,10 .endif .else print "empty file",13,10 .endif fclose hFile .else print "can't open file",13,10 .endif inkey exit main endp end main
-
ok, im Code fehlt noch
free pBuffer
an der richtigen Stelle
-
Danke euch nochmals
(Mal gucken, wie of ich das noch schreiben werde)
Mittlerweile habe ich das Problem des Auslesens auch selbst gelöst.
Ich hatte mich in der msdn verlesen:This parameter can be NULL only when the lpOverlapped parameter is not NULL.
Das "only" habe ich leider ignoriert.
Das Schlüsselwort "addr" habe ich allerdings immer noch nicht ganz verstanden. ich habe in meinem Programm sehr of "addr" verwendet und trotzdem taucht kein einziges Mal der Befehl lea auf.
Und warum muss ich dieses Schlüsselwort auch bei C-Strings verwenden. Schliesslich verweist ein C-String immer auf das erste Byte des Strings, oder?
-
@night@ schrieb:
ich habe in meinem Programm sehr of "addr" verwendet und trotzdem taucht kein einziges Mal der Befehl lea auf.
masm erkennt, ob du eine lokale oder global Variable mit dem ADDR-Operator benutzt: bei globalen Var. ist es (i.a.R.) nicht nötig mit LEA zu Arbeiten.
@night@ schrieb:
Schliesslich verweist ein C-String immer auf das erste Byte des Strings, oder?
Wenn du das Label eines Strings angibst (bei invoke), interpretiert masm es so, dass du die ersten 4 Bytes des Strings als DWORD haben möchtest. Wenn du die Adresse haben willst, musst du explizit den OFFSET oder ADDR Operator verwenden.
-
Danke, jetzt habe ich es verstanden. Muss ich denn in manchen Fällen anstatt von addr offset verwenden?
Ausserdem hänge ich (mal wieder) an einem Problem.
Ich spiele gerade mit der Funktion GetCursorPos herum und möchte eine x-Position in einer globalen Variable speichern. Nur leider weigert sich masm den Kopiervorgang vorzunehmen.;fenster.asm .386 .MODEL flat,stdcall option casemap:none INCLUDE \masm32\include\windows.inc INCLUDE \masm32\include\user32.inc INCLUDE \masm32\include\kernel32.inc INCLUDELIB \masm32\lib\user32.lib INCLUDELIB \masm32\lib\kernel32.lib includelib \masm32\lib\msvcrt.lib include \masm32\include\msvcrt.inc include \masm32\macros\ucmacros.asm long TYPEDEF DWORD GetCoordsofCurve PROTO .DATA ausgeben db "%d", 0 zaehleranzeige db "Datei: ", 13, 10, 0 dwZaehler dd 0 .DATA? ;uninitialisierte Daten ScreenXleft dword ? ScreenXright dword ? ScreenYtop dword ? ScreenYnottom dword ? .CODE start: invoke GetCoordsofCurve invoke ExitProcess, 0 GetCoordsofCurve PROC local pStruct:POINT schleifena: invoke GetAsyncKeyState, VK_CONTROL cmp eax, 0 jne schleifenende jmp schleifena schleifenende: invoke GetCursorPos, addr pStruct mov ScreenXleft, pStruct.x ;hier hängts ret GetCoordsofCurve ENDP END start
Das Problem liegt also hier:
mov ScreenXleft, pStruct.xScreenXleft = dword
pStruct.x = longGibt es da überahupt einen Unterschied?
-
Es kann nur einen Speicheroperanden geben. Du hast aber in der Zeile zwei. Also entweder push pStruct.x und pop ScreenXleft oder über ein Register (lea, mov).
Die Schleife lässt sich übrigens vereinfachen (falls du sie nicht abändern möchtest):
schleifena: invoke GetAsyncKeyState, VK_CONTROL cmp eax, 0 je schleifenna
-
ADDR kann man immer verwende, OFFSET nur mit Ausdrücken, die schon während der Übersetzung\dem Linken bekannt sind.
Zu deinem Problem: wie schon gesagt, in der x86-Archetektur gibt es kein Befehle, die 2 Speicheroperanten haben (Ausnahmen bestätigen die Regel ^^) - du musst immer über ein Register gehen. In deinem Fall gib es einen kleine macro der es erlaub 32Bit Werte im Speicher zu übertragen:m2m ScreenXleft,pStruct.x
wird Übersetzt zu:
push pStruct.x pop ScreenXleft
-
Jetzt habe ich alle Befehle mov Befehle mit 2 Speicheroperanden mit m2m ausgetauscht. An den anfang habe ich jetzt geschrieben:
m2m MACRO
, weil es sonst wieder an Fehlern gehagelt hätte.
Nur leider bekomme ich jetzt folgenden Fehler:
D:\masm32\projects\Project1\Project.asm(97) : fatal error A1008: unmatc
hed macro nesting;fenster.asm .386 .MODEL flat,stdcall option casemap:none INCLUDE \masm32\include\windows.inc INCLUDE \masm32\include\user32.inc INCLUDE \masm32\include\kernel32.inc INCLUDELIB \masm32\lib\user32.lib INCLUDELIB \masm32\lib\kernel32.lib includelib \masm32\lib\msvcrt.lib include \masm32\include\msvcrt.inc include \masm32\macros\ucmacros.asm includelib \masm32\include\gdi32.lib include \masm32\include\gdi32.inc long TYPEDEF DWORD m2m MACRO GetCoordsofCurve PROTO mainProc PROTO ;20 .DATA DCParam db "DISPLAY",0 ;wird für CreateDC benötigt ausgeben db "%d", 0 zaehleranzeige db "Datei: ", 13, 10, 0 dwZaehler dd 0 .DATA? ;uninitialisierte Daten ScreenXleft dword ? ScreenXright dword ? ScreenYtop dword ? ScreenYbottom dword ? .CODE start: invoke GetCoordsofCurve invoke ExitProcess, 0 mainProc PROC local myDC:HDC local yZaehler:dword local xZaehler:dword m2m yZaehler, ScreenYtop ;40 m2m xZaehler, SreenXleft ;===============================>hier gehts los invoke CreateDC, addr DCParam, NULL, NULL, NULL mov myDC, eax ;DC erstellen ;======> dec ScreenYtop ;um einen kleinen Denkfehler vorzubeugen ;) schleifenanfang: mov yZaehler, ScreenYtop schleifenanfangY: m2m xZaehler, ScreenXleft ;resetten cmp yZaehler, ScreenYbottom je schleifenanfang inc yZaehler schleifenanfangX: ;pixel auslesen cmp xZaehler, ScreenXright ;falls der Bildschirm einmal abgewandert wurde je schleifenanfangY inc xZaehler ;nächster pixel jmp schleifenanfangX ret mainProc ENDP GetCoordsofCurve PROC ;sammelt informationen über bildschirm local pStruct:POINT schleifenaXleft: ;links oben invoke GetAsyncKeyState, VK_CONTROL cmp eax, 0 jne schleifenendeXLeft jmp schleifenaXleft schleifenendeXLeft: invoke GetCursorPos, addr pStruct m2m ScreenXleft, pStruct.x m2m ScreenYtop, pStruct.y ;===========================>YBottom schleifenaYBottom: ;rechts unten invoke GetAsyncKeyState, VK_CONTROL cmp eax, 0 jne schleifenendeYBottom jmp schleifenaYBottom schleifenendeYBottom: invoke GetCursorPos, addr pStruct m2m ScreenYbottom, pStruct.y m2m ScreenXright, pStruct.x ret GetCoordsofCurve ENDP END start
Tschuldigung, dass ich euch jetzt mit Fragen löchere, aber ich habe noch ein paar grobe Verständnissfehler^^
€dit: Gibt es eigentlich die Option die Zeilennummerierung bei masm32 einzuschalten? Assembler erscheint mir sowieso wie ein Wall of Text, aber ohne Nummerierung kann ich mit den Fehlern meist gar nichts anfangen...
€dit2: Sieht so aus als ob ich das Makro falsch definiert habe...
-
du brauchst den macro nicht zu Definieren - includier einfach \masm32\macros\macros.asm
m2m macro op1,op2 push op2 pop op2 endm
Zur Zeilennummerierung: einfach den Quellcode in einem Texteditor öffnen, der eine Zeilenummerierung anbietet.
-
Jetzt funktioniert endlich alles wie es soll. Aufgrund des Denkfehlers bei mov und cmp wurde ich massenhaft mit Fehlern zugeschüttet.
Mittlerweile habe ich auch einigermaßen verstanden, wie man Macros selbst definiert.
Ausserdem bist du jetzt für mich ein Genie. Danke dir nochmal für deine Hilfe€dit: Mhmm. nach Aviras Meinung bin ich jetzt ein Virenprogrammierer...