Assembler-Code.



  • Guten Tag!
    Das ist ein Assembler-Code.

    DATEN SEGMENT
    Meldung db "Assembler ist gut"
    db "$"
    DATEN ENDS

    CODE 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 21h

    CODE 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
    ausgeblendet

    Disassembly of File: C:\asmC\FIRST.EXE
    Code Offset = 00000220, Code Size = 00000010
    Data Offset = 00000000, Data Size = 00000000

    Number 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, ax

    Die 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önnte

    Danke
    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.
    mit

    mov 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,ax

    ist 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.


Anmelden zum Antworten