Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Delphi Maschinensprache und Assembler - ein kleines Beispiel (https://www.delphipraxis.net/31816-maschinensprache-und-assembler-ein-kleines-beispiel.html)

MaBuSE 14. Okt 2004 12:47


Maschinensprache und Assembler - ein kleines Beispiel
 
Aufgrund des diesen Beitrages Maschinensprache habe ich mich entschlossen ein kleines Tutorial zu schreiben:

Diskussionen bitte in obigen Threat schreiben, Erweiterungen zum Tutorial bitte hier ;-)

Zitat:

Zitat von phXql
Maschinencode is doch nich das selbe wie Assembler. Assembler hat ja schon n paar befehle, aber maschinencode is wirklich nur "strom da" und "strom nich da" (1 bzw 0)... Oder hab ich da mal wieder nich aufgepasst? ^^

Mir ist nun klar geworden, dass es Sinn macht etwas mehr zu Thema zu schreiben ;-)

Also...
  • Computer arbeiten digital. (Digital bedeutet logisch es gibt nur 1 und 0 bzw. auf der elektrischen Ebene es gibt nur Strom an und Strom aus.)
    Das kleinste Digitale Element ist ein Bit. (Ein Bit kann 1 oder 0 sein.)
  • Wenn man mit Bits arbeitet, benutzt man das Binäre (duale) Zahlensystem.
    Damit kann man mit 2 Bit 4 Zustände, mit 4 Bit 16 Zustände und mit 8 Bit 256 Zustände darstellen.
    Code:
    bin dez
    00 = 0
    01 = 1
    10 = 2
    11 = 3
  • 8 Bit werden in einem Byte zusammengefasst.
    Zur Darstellung benutzt man das Hexadezimale Zahlensystem. (Hier gibt es Ziffern von 0 bis F.)
    Code:
    bin   hex  dez
    0000 = 0   = 0
    0001 = 1   = 1
    0010 = 2   = 2
    0011 = 3   = 3
    0100 = 4   = 4
    0101 = 5   = 5
    0110 = 6   = 6
    0111 = 7   = 7
    1000 = 8   = 8
    1001 = 9   = 9
    1010 = A  = 10
    1011 = B  = 11
    1100 = C  = 12
    1101 = D  = 13
    1110 = E  = 14
    1111 = F  = 15
    Die 8 Bits 11010110 werden in 2 4er Gruppen aufgeteilt: 1101 0110
    und dann, nach der Tabelle oben, Hexadezimal dargestellt:
    1101 = D und 0110 = 6 -> 11010110 = D6
    So werden statt 8 Zeichen nur noch 2 benötigt (viel weniger zu tippen ;-))
  • Ein Maschinen Programm könnte also wie folgt aussehen:
    EB 0C 68 65 6C 6C 6F 20 77 6F 72 6C 64 24 BA 02 01 B4 09 CD 21 B8 01 4C CD 21
    Dieses Programm gibt auf dem Bildschirm (in der Dos Box) "hello world" aus :mrgreen:
  • Es ist natürlich sehr schwer sich die Befehle in dieser Form zu merken, deshalb wurden für die einzelnen Befehle kleine Kürzel (so genannte mnemonische Symbole, kurz Mnemonics)
    • EB bedeutet JMP (Jump = Springe nach)
    • 0C ist der Parameter von JMP und bedeutet 12 Byte
      -> Der 1. Befehl ist also ein "goto 12 Bytes weiter"
    • 68 65 6C 6C 6F 20 77 6F 72 6C 64 24 ist die hexadezimale Darstellung von "hello world$" (genau 12 Bytes :-))
    • BA bedeutet MOV DX, Wert
    • 02 01 Ist der Wert (Es werden Low und High Byte vertauscht -> Wert = 0102)
      -> MOV DX, 102 -> Dieser Befehl speichert den Wert 0102 in dem Register DX des Prozessors ab
    • B4 bedeutet MOV AH, Wert
    • 09 ist der Wert
      -> MOV AH, 09 -> speichert den Wert 09 im Register AH ab
    • CD bedeutet INT Wert
    • 21 ist der Wert
      -> INT 21 -> ruft den Software Interupt 21 auf
      -> hier wird die DOS Funktion 09 mit Parameter 102 aufgerufen
      -> diese gibt den Text ab Adresse 102 bis zum $ aus
    • B8 bedeutet MOV AX, Wert
    • 01 4C ist der Wert (Es werden Low und High Byte vertauscht -> Wert = 4C01)
      -> MOV AX, 4C01 -> schreibt 4C01 in Register AX
    • CD bedeutet INT Wert
    • 21 ist der Wert
      -> INT 21 -> ruft den Software Interupt 21 auf
      -> hier wird die DOS Funktion 4C 01 aufgerufen
      -> diese beendet das Programm
  • hier noch mal das ganze Listing:
    Code:
    125A:0100 EB0C         JMP    010E
    125A:0102 68656C6C6F20  DB     "hello "
    125A:0108 776F726C6424  DB     "world$"
    125A:010E BA0201        MOV    DX,0102
    125A:0111 B409          MOV    AH,09
    125A:0113 CD21          INT    21
    125A:0115 B8014C       MOV    AX,4C01
    125A:0118 CD21          INT    21
  • so sieht’s als Hex Dump aus:
    Code:
    125A:0100  EB 0C 68 65 6C 6C 6F 20-77 6F 72 6C 64 24 BA 02   ..hello world$..
    125A:0110  01 B4 09 CD 21 B8 01 4C-CD 21 00 00 00 00 00 00   ....!..L.!......
  • Wie kann ich das denn selbst ausprobieren?
    Es gibt im MS DOS / Windows ein Programm Debug.exe mit dem das geht.
    Dieser Debugger wird von der Dos Box aus gestartet:
    Code:
    C:\>debug
    -n c:\temp\hello.com
    -a
    11D1:0100 jmp 130
    11D1:0102 db "hello world",24
    11D1:010E mov dx,102
    11D1:0111 mov ah,9
    11D1:0113 int 21
    11D1:0115 mov ax,4c01
    11D1:0118 int21
    11D1:011A
    -a 100
    11D1:0100 jmp 10e
    11D1:0102
    -rcx
    CX 0000
    :1a
    -w
    0001A Bytes werden geschrieben.
    -q

    C:\>c:\temp\hello.com
    hello world
    C:\>
    Anmerkung zu obigem Beispiel:
    Ich habe erst einen "jmp 130" eingegeben, da ich ja nicht wusste wie lange mein Text wird.
    Vor "mov dx,102" steht die Adresse "010E".
    Diese Adresse habe ich am Schluss nochmal korrigiert "jmp 10e"

    mit "n dateiname" legen wir den Dateinamen fest.
    mit "a" schalten wir in die Assembler Eingabe um
    mit "rcx" legen wir die Programmgröße fest (nach "Int 21" steht "xxxx:011A", da wir bei 0100 begonnen haben und nun bei "011A" sind ist das Programm "1A" Byte groß) ("1A" hex = 26 dez)
    mit "w" speichern wir das Programm ab
    mit "q" beenden wir den Debug.exe

    Im Debug.exe kann man mit ? eine kleine Hilfe (Befehlsübersicht) bekommen.

So das sollte als Info reichen.

Hier kann man noch etwas mehr dazu lesen:
Viel Spaß
Dr. MaBuSE

MaBuSE 15. Okt 2004 08:58

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Hallo,
ich wurde folgendes gefragt:
Zitat:

...ich hab eine kleine Frage an dich:
Kennst du eine gute Dokumentation zu debug? ...
Diese Seite hier ist ganz gut:
MS-DOS DEBUG Program

gefunden mit:
Bei Google suchenDOS DEBUG.EXE

Viel Spaß
Dr. MaBuSE

Nicodius 16. Okt 2004 09:35

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
mabuse ich seh die seite nicht ;)

MaBuSE 18. Okt 2004 09:02

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zitat:

Zitat von Nicodius
mabuse ich seh die seite nicht ;)

bei mir geht's ;-)

Da diese Seiten zur privaten Verwendung kopiert werden dürfen,
Code:
This page may be freely copied for PERSONAL use ONLY !
( It may NOT be used for ANY other purpose unless you have
first contacted and received permission from the author ! )
habe ich Sie Dir per PM geschickt. (Hier werde ich die Seiten ohne vorherige Genehmigung des Autors nicht posten UrhG)

Pseudemys Nelsoni 13. Dez 2004 23:14

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zitat:

bin hex dez
0000 = 0 = 0
0001 = 1 = 0
0010 = 2 = 0
0011 = 3 = 0
0100 = 4 = 0
0101 = 5 = 0
0110 = 6 = 0
0111 = 7 = 0
1000 = 8 = 0
1001 = 9 = 0
1010 = A = 10
1011 = B = 11
1100 = C = 12
1101 = D = 13
1110 = E = 14
1111 = F = 15

die ganzen 0en rechts stimmen aber nicht oder?

MaBuSE 14. Dez 2004 07:53

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zitat:

Zitat von Pseudemys Nelsoni
die ganzen 0en rechts stimmen aber nicht oder?

Nein. Dort müsste auch 0 bis 9 stehen (wie bei hex)

Das ist ein sogenannter "Copy & Paste" Fehler

[edit]
Das Tutorial oben wurde geändert. Die Tabelle ist nun richtig.
[/edit]

Dussel 19. Okt 2005 10:23

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zu dem Programm habe ich mal zwei Fragen:
Erstens: Ich habe das Programm mal geschrieben und jetzt kann ich es nicht mehr löschen. Es kommt die Fehlermeldung, dass die Datei von einem anderen Programm genutzt wird. Liegt das jetzt am Programm oder an meinem PC?
Zweitens: Ist das Programm jetzt komplett Betriebssystemunabhängig oder braucht es immer noch DOS? Maschinensprache ist ja normalerweise unabhängig, aber in der Beschreibung steht, dass DOS Funktionen aufgerufen werden.

NicoDE 19. Okt 2005 10:37

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zitat:

Zitat von Dussel
Ich habe das Programm mal geschrieben und jetzt kann ich es nicht mehr löschen.

Bug im Explorer - siehe Win98 se Kann keine Anwendungen mehr löschen

Zitat:

Zitat von Dussel
Ist das Programm jetzt komplett Betriebssystemunabhängig oder braucht es immer noch DOS?

INT 21 ist ein Interrupt der von MS-DOS-kompatiblen Betriebssystemen zur Verfügung gestellt wird (dazu gehört auch NTVDM (NT Virtual DOS Machine), landläufig auch als "Dos-Box" bezeichnet).

tommie-lie 19. Okt 2005 10:40

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zitat:

Zitat von Dussel
Ist das Programm jetzt komplett Betriebssystemunabhängig oder braucht es immer noch DOS? Maschinensprache ist ja normalerweise unabhängig, aber in der Beschreibung steht, dass DOS Funktionen aufgerufen werden.

Richtig, und genau aus dem Grund benötigt es MS-DOS oder ein dazu API-kompatibles. INT 21h wird von DOS bereitgestellt, Funktion 9 daraus auch. Ein anderes Betriebssystem könnte allerhand andere Funktionen dort unterbringen. Bis zum Aufruf von "INT 21" läuft das Progrmam also noch unter jedem Betriebssystem, das die COM-Datei überhaupt laden kann, danach wird es nur auf jenen Betriebssystemen laufen, die die gleiche API haben wie MS-DOS.

Edit: Ach verdammt, der olle Nico war schon wieder schneller...

Dussel 19. Okt 2005 19:47

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Dann eine weitere Frage: Gibt es das Programm auch als komplett eigenständiges Programm, so dass ich es z.B. auf einer leeren Festplatte oder auf nicht DOS basierenden Betriebssystemen ausführen könnte?
(Darf ich diese Fragen eigentlich hier stellen oder ist das in einem Tutorial nicht so erwünscht?)

tommie-lie 19. Okt 2005 21:01

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Wenn die Fragen nicht erwünscht sein sollten, haben die Moderatoren eine Funktion, um Beiträge abzusplitten.

Zitat:

Zitat von Dussel
Dann eine weitere Frage: Gibt es das Programm auch als komplett eigenständiges Programm, so dass ich es z.B. auf einer leeren Festplatte oder auf nicht DOS basierenden Betriebssystemen ausführen könnte?

Ja, gibt es theoretisch:
Code:
/*
  Copyright (C) 2004  Thomas Liebetraut

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/


/*
  __History__:
  0.01 (2004-01-15):
    - added function print_string
    - Basic stack and initialization
*/


.code16         /* 16bit RealMode code */
.intel_syntax  /* I am one of the few people who HATE AT&T-style ;-) */


    /* make sure to be at 7c0h:00 instead of 00:7c00h*/
    jmp 0x07c0, offset start


    /* here we really begin to do something */
start:
    /*
     *  We definitely need a stack
     */
    cli            /* we don't have a stack in the next few nanoseconds ;-) */
    mov ax, 0x07e0      /* 0x7c0 + 512 bytes */
    mov ss, ax
    mov ax, 512     /* 512 bytes for the stack should be enough to start with */
    mov sp, ax

    mov ax, 0x07c0  /* and by the way, update DS */
    mov ds, ax
    sti            /* now we have a proper stack, no problems for interrupts */    /*
     *  the stack is now just behind the bootsector
     */

    /* ensure to be in the correct graphics mode */
    mov ax, 0x0003
    int 0x10



    /*
     *  and clear the screen, just in case the BIOS behaves odd
     */
clear_scr:
    /* NOTE: we assume non-MDA and non-HGA! */
    mov ax, 0xb800
    mov es, ax
    mov bp, 0x00
    mov cx, 2000
    lp_clrscr:
        mov ax, 0x0700  /* color, character "0" */
        mov es:[bp], ax /* output goes to page 0, color */
        add bp, 2
    loop lp_clrscr

    /* and move to the top left corner */
    mov ax, 0x0200
    mov bx, 0x0000
    mov dx, 0x0000
    int 0x010

    /*
     *  Now, the screen and everything is initialized and we can start
     *  to work.
     */

load_stage2:
    /* first, print message saying what we're doing now */
    mov si, offset msg_load
    call print_string

    /* get the boot drive */


    jmp halt /* stop here */


/*
 *  print_string puts a string to the screen at the current
 *  cursor's position.
 *  The string must be terminated with a zero-byte (C-style string)
 *  and is interpreted by the BIOS according to BELL standards.
 *  The string is expected to be at DS:SI.
 *
 *  NOTE: After a call to print_string, SI points to the end of the string!!!
 */
print_string:
    push ax        # safe the used registers
    push bx

    mov ah, 0x0e
    mov bx, word ptr 0x0000
    print_loop:
        mov al, byte ptr [si]
        cmp al, 0x00
        jz ps_halt
        int 0x10
        inc di
    jmp print_loop

    ps_halt:
    pop bx
    pop ax
    ret



halt:
    cli
    HLT




/*
 *  Data section
 *  All variables and static data (mainly messages) goes here
 */
msg_load:
    .ascii "Loading stage 2...\x0d\x0a\x00"


/*
 *  Pad the binary with security code (normally we should never jump there)
 *  and append boot signature
 */
.fill (510 - .)/2, 2, 0xF4F4
.byte 0x55, 0xAA
Zu kompilieren mit dem GNU Assembler (GAS) und zu Speichern im ersten Sektor einer beliebigen Diskette und bootbar mit jedem IBM-kompatiblen PC-BIOS.
War mal als kleiner Bootloader zum Rumspielen gedacht (daher am Ende die eigenartigen Kommentare), läuft nur bis er den String ausgibt. Zwar ein wenig komplexer aufgebaut als Marcs Beispiel, aber dafür muss man sich um die Länge des Strings keine Sorgen machen (solange er nicht länger ist als 510-(assemblierter Programmcode) Byte. Um es noch weiter zurechtzustutzen, damit wirklich nur der String ausgegeben wird, bin ich jetzt zu faul.

MaBuSE 20. Okt 2005 09:19

Re: Maschinensprache und Assembler - ein kleines Beispiel
 
Zitat:

Zitat von Dussel
(Darf ich diese Fragen eigentlich hier stellen oder ist das in einem Tutorial nicht so erwünscht?)

Es sollte pro Sachfrage jeweils ein eigenes Thema erstellt werden.
Wenn die Fragen so stark zusammenhängen, das sie als eine Frage anzusehen sind, natürlich nicht.

Die Frage sollte nicht in der Sparte Tutorials gestellt werden, sondern in einer zur Frage passenden Sparte.
Dann findet sich auch schneller jemand der antwortet.

Was Tutorials angeht, ist es eigentlich nicht gewünscht, Fragen anzuhängen.
Das macht das Tutorial unübersichtlich.

Dazu gibt es die "Diskussionsthemen"
(Das steht aber eigentlich auch oben im Tutorial ;-)

Zitat:

Zitat von MaBuSE
Aufgrund des diesen Beitrages Maschinensprache habe ich mich entschlossen ein kleines Tutorial zu schreiben:

Diskussionen bitte in obigen Threat schreiben, Erweiterungen zum Tutorial bitte hier ;-)

Ich freue mich, das Dir mein Tutorial gefällt.
Viel Spaß
MaBuSE


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:20 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz