Assembler-Code.
-
Guten Tag!
Das ist ein Assembler-Code.DATEN SEGMENT
Meldung db "Assembler ist gut"
db "$"
DATEN ENDSCODE SEGMENT
ASSUME CS:CODE,DS:DATEN
Anfang: mov ax,DATEN
mov ds,ax
mov dx,offset Meldung
mov ah,9
int 21h
mov ah,4Ch
int 21hCODE ENDS
END Anfang-------------------------------------------------------------
-------------------------------------------------------------
-------------------------------------------------------------
-------------------------------------------------------------Und der Code unten auch (nach dem dissammblieren mit W32Dasm)
1. Welche von diesen beiden ist wirklich der Assembler-Code?
2. Wo ist z.B die Zeichenkette "Assembler ist gut" bei dem unteren
Code?
3. Wer kann mir bitte den unteren Code einwenig erklären?
4. Was hat es mit Offset hier in dem Fall auf sich?
Was macht Offset hier z.B in dem Code ganz konkret?
(bedeutet offset nicht ausgleich)5. Wie kann man mit W32Dasm debuggen (beispielsweise bei dem
unteren Code).Wenn ich debuggen möchte gehe ich über GoTo Code
Start und bei der Option Debug ist alles ausgeblendet.
Bei mir debuggen außer attach to an activ process alles
ausgeblendetDisassembly of File: C:\asmC\FIRST.EXE
Code Offset = 00000220, Code Size = 00000010
Data Offset = 00000000, Data Size = 00000000Number of Objects = 0001 (dec), Imagebase = 00000000h
Object01: RVA: 00000000 Offset: 00000220 Size: 00000010 Flags: 00000000
Number of Imported Modules = 0 (decimal)
+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++
+++++++++++++++++++ EXPORTED FUNCTIONS ++++++++++++++++++
Number of Exported Functions = 0000 (decimal)+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object BinaryCode **************
Program Entry Point = 0001:0000//********************** Start of Code in Segment: 1 **************
//******************** Program Entry Point ********
:0001.0000 B80000 mov ax, 0000
:0001.0003 8ED8 mov ds, ax
:0001.0005 BA0000 mov dx, 0000
:0001.0008 B409 mov ah, 09
:0001.000A CD21 int 21
:0001.000C B44C mov ah, 4C
:0001.000E CD21 int 21
-
Der String liegt im Datensegment, nicht im Codesegment. W32Dasm hat eine Schaltfläche "String resources". Da müsste das stehen.
Eine Zeile disassemblierter Code ist ganz einfach aufgebaut:
:0001.0003 8ED8 mov ds, axDie ersten Zahlen sind die Position des Codes im RAM. Das danach (8ED8) ist der Maschinencode, also der compilierte Code, der in der exe steht.
Danach steht, was dieser Maschinencode macht.btw:
Bevor du Programme disassemblierst, würde ich dir raten mal ein gutes Assembler-Tutorial oder Buch durchzulesen. offset sollte auf den ersten Seiten erklärt sein.
-
cd9000 ich danke dir für die Antworten.
Was ist eigentlich mit den anderen Fragen ich kann z.B nicht debuggen
oder unter "String resources" steht bei mir nicht drin.
Welche von beiden Codes ist was???
oder Zitat "8ED8 ist der Maschinencode" wie kommt man auf 8ED8?
Ich bin wirklich ein Afänger kann zwar programmieren (Java, etwas C)
aber Asm ist doch etwas anderes. Man muss zunächst die Grundkonzepte
verstehen. Ich wäre sehr dankbar wenn man die obengestellten Fragen
etwas ganauer beantworten könnteDanke
Grüße
-
Ups, "String Resources" gibt's ja nur bei Windows-Anwendungen. Du musst auf "Hex Display of Data Object/Segment" im Menu "HexData" klicken.
Maschinencode muss man nicht verstehen. Maschinencode ist das, was die CPU sieht und ausführt. Es sind nur Bytes.
Damit man sich nicht mit diesen hunderten von Hex-Codes rumschlagen muss, wurde Assembler erfunden.Der Assembler macht aus Assemblercode Maschinencode. In der exe-datei steht dann nur noch Maschinencode.
-
diese offset frage scheint dich ja echt zu quälen. ok ich werds mal versuchen zu erklären.
ich empfehle dir das ganze "langsam" durchzulesen. nimm dir zeit für die grundlagen.offset heisst in diesem fall "zusatz"
wenn du daten im datensegment reservierst also zB:
DATEN SEGMENT X db 2 Y db 3 Z db 7 DATEN ENDS
dann werden diese so weit ich weiss vom betriebssystem vor dem ausführen des programms irgendwo ins RAM geladen.
mitmov ax,DATEN mov ds,ax
lädst du nun die adresse deiner daten in das register DS. diese adresse ist nix weiter als eine zahl, die angibt an welcher stelle im RAM deine daten beginnen.
nehmen wir an dieser block stellt das RAM dar* ---------------------------- | | | | | | | | | | |0123456789 | DATEN =>|Assembler ist gut | | | | | | | | | | | | | | | | | | | ----------------------------
jetzt macht man das so dass man diese adresse im DS register stehen lässt und wenn du nun auf einzelne bytes deiner daten zugreifen willst, dann musst du der CPU sagen welches byte du gerade meinst.
hier kommt nun der offset.
nehmen wir an du willst auf das erste 'e' in deinem sting zugreifen. du siehst oben dass es an der stelle #3 steht. das heisst der offset des ersten buchstabens 'e' oder besser gesagt, des bytes in dem der ascii code für das 'e' steht ist 3.
willst du also zB nun in das register AL den ascii code im byte #3 laden, dann machst du folgendes:mov di,3 ; lade offset ins register DI mov al,ds:[di]
ds:[di] gibt für den prozessor die vollständige adresse dieses bytes an.
naja sie ist nur fast vollständig und wird intern noch bearbeitet.
es passiert fogendes:
die zahl die im register DS steht wird mit 16 multipliziert (warum musst du noch nicht wissen), so wird die stelle ermittelt an der deine daten im RAM beginnen. danach wird zu diesem wert der offset addiert, also
ds*16+di ist die vollständige adresse des bytes im RAM.
der offset ist also nichts weiter als eine zahl, die angibt wo ein bestimmtes byte in deinem datensegment steht.
noch ein beispiel, nehmen wir wieder das segment von vorhin:DATEN SEGMENT X db 2 Y db 3 Z db 7 DATEN ENDS
nehmen wir an du willst ganz umständlich den wert von Y in das AL register laden. dann kannst du folgendes machen:
mov di,offset Y ; lade die nummer des bytes in dem der wert von Y steht mov al,ds:[di]
für den assembler sind X,Y und Z nichts weiter als zahlen, oder marken. diese markieren bestimmte stellen im datensegment, die für dich von bedeutung sind:
DATEN SEGMENT X db 2 Y db 3 array db 2 db 4 db 6 db 8 Z db 7 DATEN ENDS
so wie zB "array" eine wichtige stelle markiert, nämlich den beginn einer menge von daten, die eine bestimmte bedeutung haben können.
du siehst zB dass ganz vorne im datensegment das X steht. das heisst dass der offset von X 0 beträgt.
Y ist ein byte weiter also beträgt der offset von Y 1. noch ein byte weiter fängt das array an das heisst der offset von array beträgt 2.
willst du also auf das erste byte in deinem array zugreifen dann kannst du entwerder volgendes schreiben:mov di,offset array mov al,ds:[di]
oder das:
mov di,2 mov al,ds:[di]
eigentlich ist die 2 version das, was der assembler aus deinem code macht. er wird alle X, Y, Z ... usw in deinem code durch die zahlen ersetzen, die diese symbolisieren, falls du die direktive "offset" benutzt.
es ist auch möglich dass du zB auf ein anderes byte in deinem array zugreifen willst, dann kannst du auch schreiben:
mov di,offset array+1
dieses wird nun die adresse des bytes in das DI register laden in dem die zahl 4 steht.
mit
mov al,ds:[di]
lädst du nun die zahl 4 in das register AL.
diese zahl 1 die wir zum offset von array addiert haben ist auch ein offset. bezieht sich aber diesmal auf das array.
....................
warum ds*16+di (also warum ds*16)
die cpu hat unter dos standardmäßig 1MB ram zur verfügung. man muss nun der cpu sagen welches byte man in diesen 1MB gerade meint.
die adressleitung von der cpu zum ram konnte 20bit grosse adressen verarbeiten.
mit 20 bit kannst du zahlen von 0 bis 1048577 darstellen. diese 20 bit reichen also aus um jedes byte in dem 1MB anzusprechen.
das problem war nun, dass die cpu selbst nur 16bit grosse register zur verfügung hat. mit 16 bit kann man nur zahlen von 0 bis 65535 darstellen. das heisst ein 16bit register alleine reicht nicht aus, um jedes byte im 1MB ram anzusprechen.
deshalb hat man zur adressbildung 2 register benutzt. zB ds:di
wenn du 2^20 durch 2^16 teilst dann merkst du dass das ergebnis 16 ist.
wenn man also das ds register alleine nehmen würde und es jedesmal mit 16 mutipliziert dann kann man alle 16 byte stücke in dem 1MB adressieren:
1MB hat also insgesamt 65536 SEGMENTE, die alle 16 byte gross sind und mit dem
ds register kannst du nun angeben, welches dieser segmente gemeint ist.
nun will man in diesem 16 byte grossem segment alle 16 byte ansprechen können.
das macht man mit dem offset register in diesem fall di.
will man also byte #5 in einem segment ansprechen so lädt man die 5 in das DI register.
die cpu wird dann intern die richtige adresse mit ds*16+di ausrechnen und an die adressleitung weitergeben.
-
Hi!
wasiliy Weltklasse Leistung, allerdings muss ich mir das wirklich in aller
Ruhe durchlesen.
Ich danke vielmals an alle die sich die Mühe gemacht haben.Woher weiss ich z.B das die Zeichenkette "Assembler ist gut$" von ds:0000h bis ds:0012h liegt. Wer sagt mir das oder entnehme ich das?
Übrigens warum kann ich die Zeichenkette als solche nicht wieder im Code
finden.
Kennt jemand ein Tutorial über "wie benutze ich W32Dasm"
zwecks debuggen und wegen der Schaltfläche "String resources usw
denn da sollen solche Strings sein.Grüße
-
wenn du davor keine daten definiert hast dann gibt es keinen grund für den string wo anders zu sein.
hier z.B ein segment:
daten segment db 0 ; byte #0 db 4 ; byte #1 db 2 ; byte #2 db 12 ; ... string db 'hallo welt$' daten ends
der string 'hallo welt$' wäre hier bei ds:04.
das kannst du ablesen wenn du die bytes zählst. du fängst oben an zu zählen und das oberste, oder erste byte hat immer die #0 usw...dein string findest du nicht im code weil das code segement ein eigenes segment ist und eventuell ganz wo anders im ram zu finden ist. kann zB so sein:
* ---------------------------- | | | | | | | | | | |0123456789 | DATEN =>|Assembler ist gut | | | | 123498754613945 | | dafghfdh | | | | | | | CODE =>| | | | | | ----------------------------
oder so:
* ---------------------------- | | | | CODE =>| | | | | | |0123456789 | DATEN =>|Assembler ist gut | | | | 123498754613945 | | dafghfdh | | | | | | | | | | | | | ----------------------------
du würdest deinen string im code segment finden können, wenn du ein .com programm hättest, weil bei .com programmen die daten und der code alle im codesegment sind. die daten normalerweise nach dem code:
model tiny .code org 100h main: mov ah,09h mov dx,offset hallo int 21h ret hallo db 'hallo welt!$' end main
-
eigentlich kannst du auch ein .exe programm erzeugen, wo die daten im code sind:
model small .code main: mov ax,cs mov ds,ax mov ah,09h mov dx,offset hallo int 21h mov ah,4ch int 21h hallo db 'hallo welt!$' end main
mov ax,cs
mov ds,axist wichtig da deine daten ja im codesegment sind und die adresse des codesegments steht in cs. diese copierst du ins ds register. das ist wichtig, weil die funktion 09h des int 21h die segmentadresse deiner daten im DS register erwartet.