Ein ganz nettes Tutorial auch mit Ressourcen und ähnlichem findest du auf http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/toc.html.
Follow along with the video below to see how to install our site as a web app on your home screen.
Anmerkung: This feature may not be available in some browsers.
DATA SEGMENT ;- Beginn des Datensegments
Meldung db "Hello World" ;- Die Zeichenkette "Hello World"
db "$" ;- Endzeichen der Zeichenkette
DATA ENDS ;- Ende des Datensegment
CODE SEGMENT ;- Beginn des Codesegements
ASSUME CS:CODE,DS:DATA ;- Dem Assembler die Segmente mitteilen
Anfang: ;- Label für den Anfang des Programms
mov ax, DATA ;- das Daten...
mov ds, ax ; ...segment laden
mov dx, offset Meldung ;- den Text in das Datenregister laden
mov ah, 09h ;- dem Betriebssystem mitteilen, was wir wollen
int 21h ;- diesen Befehl ausführen (hier Ausgabe des Texts)
mov ax, 4C00h ;- dem Betriebssystem wieder mitteilen, was wir wollen
int 21h ;- diesen Befehl wieder ausführen (Programm beenden)
CODE ENDS ;- Ende des Codesegments
END Anfang ;- dem Assembler das Ende des Labels Anfang mitteilen
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
.data
MsgBoxCaption db "Window title",0
MsgBoxText db "Assembly is cool!",0
.code
start:
invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, NULL
invoke ExitProcess, NULL
end start
Du hast den Quellcode eines 16-Bit Programms gepostet. Damit kann MASM nicht mehr umgehen. Hat also nichts mit dem PC zu tun, sondern mit der Zielplattform - möchte man 16-Bit Programme assemblieren, nutzt man eben einen 16-Bit Assembler.Aber dennoch! Ich habe einen relativ neuen PC -> daraus schließe ich, dass ich wohl mit MASM (32-Bit) arbeiten kann.
MASM ist kein Befehl, sondern ein Packet mit dem Assembler ML. ML=Assembler=MASMWas jedoch nach wie vor (auch nach Ändern der Umgebungsvariablen) nicht funktioniert ist der MASM Hallo.asm - Befehl!!!
An den verwendeten Befehlen/Befehlsparametern, würde ich mal behaupten1. Wie erkenne ich nun den Unterschied zwischen 16-bit Code und 32-bit Code?
mov ah, 09h
Doch gibt es.2. Gibt es im 32-bit Assemblercode etwa keine MOV, ADD, INT CMP etc mehr??
Der Assembler automatisiert immer wiederkehrende Prozeduren. Z.B. mit "Invoke" generiert er einen Call mit Parametern.90nops Code sieht ja schon fast aus wie ne Hochsprache...
invoke myfunc, par1,par2,par3,par4
push par4
push par3
push par2
push par1
call myfunc
JaOriginal von Gapa
Und noch ein paar Fragen:
Wenn mein Programm in den Arbeitsspeicher geladen wird, haben dann die einzelnen Befehle die selbe Adresse wie die Adressen ganz links wenn man Olly öffnet??
RAMOriginal von Gapa
Und wie nennt man den Teil des Arbeitsspeichers, in den das Programm geladen wird?
Ein Prozessor hat verschiedene Register, auf die man besonders schnell zugreifen kann.Original von Gapa
Ich verstehe einfach den Zusammenhang zwischen Prozessor (CPU) Arbeitsspeicher, Stack und Register noch nicht...
Wie oben schon erwaehnt werden normalerweise nur Parameter auf dem Stack gespeichert, aber du kannst auch Opcodes pushen und dann sowas wie "call esp" machen. Kurz: der Stack ist auch nur Speicher und solang es nicht die Groeße des Stacks ueberschreitet kannste draufladen was du willst.Original von Gapa
Werden nur Daten oder auch OP-Code in den Stack geladen? Und wann genau kommen nun die Register ins Spiel?
Als "Weg" kann man es nicht nennen - aber i.R sorgt der Compiler/Assembler für die Trennung. Im Asm Code helfen dabei die Direktive ".code/.data" oder CODE SEGMENT/DATA SEGMENTOriginal von Gapa
Ich habe zu der OP-Code - Daten-Code Trennungssache etwas im I-net gefunden.
CDW hat ja gesagt, dass der Programmierer selbst dafür sorgen muss, dass der Prozessor Daten (Variablen etc.) nicht als Befehle interpretiert.
Im Internet habe ich nun eine Quelle gefunden, welche sagt, man müsse zum Beispiel durch jmp-Befehle den Daten-teil überspringen. Stimmt das nun, oder gibt es da andere Möglichkeiten, wie man dem Prozessor sagt was OP-Code ist und was nicht.
Register sind streng genommen besonders schnnell ansprechbare Speicherbreiche, auf die man verschiedene Bitopreation anwenden kann. Stichwort dazu wäre ALU:Ich verstehe einfach den Zusammenhang zwischen Prozessor (CPU) Arbeitsspeicher, Stack und Register noch nicht...
Das bedeutet also, dass es nicht einen bestimmten Bereich im Arbeitsspeicher gibt, welcher als Stack gekennzeichnet ist, sondern dass jedes Programm seinen eigenen Stack bekommt beim Starten, oder?Wenn ein Programm gestartet wird, weist das Betriebssystem diesem nicht nur den normalen Speicher zu - es zwackt auch einen Bereich vom Speicher ab, der als Stack dienen soll.
Diese Register werden mit der Startadresse des Stacks initialisiert, dass das Programm weiß, ab wo der Stack beginnt, oder?Die Stack-Register ESP/EBP werden dann mit diesen Werten (Stackanfang) initialisiert, so dass ein Programm nach dem Start direkt einen Speicherbereich namens Stack zur Verfügung hat.
korrektOriginal von Gapa
Das bedeutet also, dass es nicht einen bestimmten Bereich im Arbeitsspeicher gibt, welcher als Stack gekennzeichnet ist, sondern dass jedes Programm seinen eigenen Stack bekommt beim Starten, oder?
nein. Zur Vereinfachung erstmal: stellt Dir vor, es läuft nur ein Programm alleine.Das heißt, ohne laufende Programme gäbe es auch keinen Stack, oder?
Und wie läuft das dann mit der Adressierung?
Sieht der Arbeitsspeicher dann etwa so aus? :
Arbeitsspeicher
1:code
2:code
..
40: daten
41: daten
...
100: stackende
101: stack
200: stackanfang
jein. Theoretisch ist es zwar so, praktisch aber wird das meistens begrenzt - das Betriebssystem blendet z.B einen Teil seiner Bibliotheken in den Speicher ein (damit das Programm diese nutzen kann). Ein Teil des Betriesbsystem ist nicht auslagerbar (d.h dieser Speicher kann von der Anwendung nicht beschrieben/freigegeben werden).Wie werden aber nun die Adressen bestimmt. Jedes Programm bekommt ja 4 GB Speicher zur Verfügung, d.h., dass ein Programm immer 4000000000 Adressen zur Verfügung hat, richtig? (denn eine Adresse hat ein Byte Speicher, oder?).
die "nächsten" 400000000 Adressen hätten eine Wert über 32-Bit und wären damit erstmal gar nicht ansprechbarWie ist da nun die Adressengebung?
Bekommt beim Starten des PCs das erste Programm, welches in den Arbeitsspeicher geladen wird, die ersten 4000000000 Adressen zur Verfügung, das 2. die nächsten 4000000000...??
Da gibt es Defaultwerte. Unter Win wird zum Beispiel im PE Header der benötigte Wert angegeben (i.r einfach ein Defaultwert seitens Linker):Und nohcmal zum Stack:
Der Stack heftet sich einfach an den Programmspeicher? Wie ist das Verhältnis Programmspeicher - Stack? Also was ich meine ist, wie viele GBs von den 4 GB sind nun Stack?
NEW EXE
+0 PE
4 WORD Machine;
....
18 Optional Header
....
34 DWORD ImageBase;
38 DWORD SectionAlignment;
3c DWORD FileAlignment;
....
5e WORD DllCharacteristics;
60 DWORD SizeOfStackReserve; <----
64 DWORD SizeOfStackCommit;
jaDiese Register werden mit der Startadresse des Stacks initialisiert, dass das Programm weiß, ab wo der Stack beginnt, oder?Die Stack-Register ESP/EBP werden dann mit diesen Werten (Stackanfang) initialisiert, so dass ein Programm nach dem Start direkt einen Speicherbereich namens Stack zur Verfügung hat.
Da gibt es verschiedene Anwendungsmöglichkeiten. Zum einen liegen die lokalen Variablen (die nur innerhalb der Funktion gültig sind) auf dem Stack. Zum anderen werden i.R Parameter über den Stack übergeben.Und man kann nur mittels den 2 Registern (ESP/EBP) mit dem Stack arbeiten? Oder wozu brauche ich diese Register überhaupt?
Ich kann doch auch einfach beispielsweise "PUSH 80" schreiben. Dann wird der Wert 80 auf den Stack gelegt, oder? (Habe aber keine Ahnung, was das bringen soll). Wenn ich diese 80 nun wieder runterholen will, dann schreibe ich POP (und dann die Adresse des Wertes 80 im Stack, oder?).
function(int a)
{
int x=1;
int y=x+1;
return y
}
wäre:
_function:
push ebp ;alten Wert sichern
mov ebp, esp ;das soll die neue Stackbasis sein, EBP zeigt im Moment auf den alten EBP Wert
sub esp, 8 ; reserviere Speicher für lokale Variablen
mov [ebp-4],1 ;initilisiere erste lokale Variable mit 1
mov eax,[ebp-4]
add eax,1
mov [ebp-8],eax ;schreibe Ergebnis in die zweite lokale Variable
;return
mov eax,[ebp-8]
sub esp,8 ;reservierten Speicher freigeben
mov esp, ebp
pop ebp ; alten EBP Wert wiederherstellen
ret
in dmesg Link wird ja schon ziemlich viel Erklärt.Eigentlich wäre das ja logisch. Denn nicht jedes Programm hat die Startadresse 0001!
Wenn ich ein beliebiges Programm in OllyDbg öffne, dann ist die erste Adresse 00401000.
Nur das komische ist, dass sich diese Adresse nie ändert...Wenn ich zwischendurch ein anderes Programm starte (also in den Arbeitsspeicher rufe) und dann nochmals das Programm in Olly öffne, ist die Startadresse wieder 00401000...wieso ist diesmal die Startadresse nicht 00401000 + 4000000000??
Wieso wächst der von unten nach oben?Stack "wächst" von unten nach oben - von größeren Adressen zu kleineren. Das ist aber nur eine Konvention. D.h der Stack hat nicht dieselbe Adresse wie der Code/Daten, sondern ist ein anderer Speicherbreich.
0001: code
0002: code
0003: code
0004: code
0005: leere Adresse <---- hier ist der Zwischenraum der Segmente Code - Daten
0006: daten
0007: daten
0008: daten
0009: daten
000A: leere Adresse <---- hier ist der Zwischenraum der Segmente Daten - Stack
000B: Stackplatz (leer)
000C: Stackplatz (leer)
000D: Stackplatz (leer)
000E: Stackplatz (leer)
Verstehe ich nicht...push ebp ;alten Wert sichern