Codeschnipsel

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Antworten
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Codeschnipsel

Beitrag von oDOSseus »

Hey. Während ich die TUI programmiert habe und ab und zu Pausen brauchte, habe ich ein paar Codeschnipsel gesucht, gefunden und modifiziert. Hier mal ein paar, die vllt. ganz nützlich sind, die aber die meisten schon kennen. Wenn ihr selber noch so schnipsel habt, fände ich es schön, wenn ihr sie auch hier postet. Natürlich meine ich nicht sowas wie "einen char von der tastatur lesen", sondern eher etwas, was man seltener braucht und an sich sehr speziell ist. Ich muss für sowas nämlich immer lange im inet suchen.

Shutdown. Wurde hier schon mehrmals von mir gepostet. Aber hier mal zentral. Funktioniert nur für >=APM 1.2

Code: Alles auswählen

           ;connect the real-mode interface
           XOR     BX, BX
           MOV     AX, 5301h
           INT     15h
           ;Set APM-Version
           ;XOR     BX, BX        ;(BX is still 0000h)
           MOV     CX, 0102h     ;Version 1.2
           MOV     AX, 530Eh
           INT     15h
           ;Set power state
           MOV     CX, 0003h     ;State 0003h = Power off
           MOV     BX, 0001h     ;All devices (not supported for APM v1.0)
           MOV     AX, 5307h
           INT     15h
Reboot. Kennt wahrscheinlich jeder. Trotzdem nochmal hier:

Code: Alles auswählen

            ;Reboot the computer
            db   0EAh
            dw  0000h
            dw 0FFFFh
Beep. Piept mit dem PC-Speaker auf einer bestimmten Hert'schen Frequenz und für eine bestimmte Zeit:

Code: Alles auswählen

            ;====Initialization====
            ;Get the speaker status an push it for restoring the status
            IN      AL,     61h
            PUSH    AX         
            ;Turn on the speaker by turning on bits 1 and 0
            OR      AL,     03h
            OUT     61h,     AL 
            ;Send some control byte
            MOV     AL ,   0B6h
            OUT     43h,     AL

            ;====BEEEEEEEEEEEP====
            ;Calculate the speaker frequence by the Hertian-frequence
            MOV     DX,   0012h
            MOV     AX,   34DEh;DX:AX = 1234DEh = 1,193,180
            MOV     BX,   3000 ;Your Hertzian-frequence
            DIV     BX
            ;Send the frequence
            OUT     42h,    AL ;Lower byte first
            XCHG    AH,     AL 
            OUT     42h,    AL ;Then higher byte

            ;====Delay====
            ;We use the delay function of int 15h
            MOV     AH,     86h
            MOV     CX,     10h
            MOV     DX,   0000h
            INT     15h       

            ;====Restore speaker status====
            ;The status was stored at the initialization
            POP     AX    
            OUT     61h,    AL
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Codeschnipsel

Beitrag von freecrac »

Da mach ich doch gleich mit. Ich beginne allerdings mit schon kleinen aber fertigen Programmen, denn ich sah keinen Sinn darin sie noch weiter zu kürzen.
Andere Schnipsel folgen im nächsten Posting.

Wer häufig mit verschiedenen Zahlensystemen zu tun hat könnte die folgenden kleinen Programme möglicherweise nützlich finden.
Die Werte die gewandelt werden sollen werden dem jeweligen Programm als Parameter übergeben.

Code: Alles auswählen

;╔════════════════════════════════════════════════════════════════════════════════════════════════╗
;║                                                                                                ║
;║  DEZ2HEX wandelt einen ganzahligen dezimalen Wert zu einem hexadezialen Wert und gibt ihn aus  ║
;║                                                                                                ║
;╚════════════════════════════════════════════════════════════════════════════════════════════════╝
.MODEL SMALL
.386
.CODE
 ORG 100h
START:    mov     ax, @DATA
          mov     di, OFFSET DEZ      ; Ziel-OFFSET der Integer-Werte
          mov     bp, OFFSET ANZ
          mov     ds, ax
          mov     es, ax
;─────────────────────────────────────────────────────────────────────────────
          mov     ah, 62h             ; Segment des PSP's ermitteln
          int   21h
          cli                         ; alle IRQ's verhindern
          mov     ds, bx              ; PSP-Segment nach DS
;-------------------------------------
          mov     si, 80h             ; Zeiger auf Parameter (Kommando-Zeile)
          mov     al, [si]            ; Anzahl der ASCII's holen, ohne CR(0Dh)
          cmp     al, 2               ;  weniger als  2 ASCII's ?
          jb  FEHLER                  ; zu wenig = Fehler !
          cmp     al, 0Bh             ;  mehr    als 11 ASCII's ?
          ja  FEHLER                  ; zu viel  = Fehler !
          dec     al
          add     si, 2               ; Zeiger auf 1.ASCII hinter dem Space
          mov     es:[bp], al
;─────────────────────────────────────────────────────────────────────────────
;   Holt dezimale ASCII-Ziffer, wandelt max. 10 Ziffern und rettet die Werte
;─────────────────────────────────────────────────────────────────────────────
          mov     cl, 0Ah             ; Anzahl Ziffern
;-------------------------------------
HOLASC:   mov     al, [si]            ; ein ASCII aus PSP holen
          inc     si                  ; PSP-Zeiger erhöhen
          cmp     al, 0Dh             ;  schon Parameter-Ende (CR) ?
          jz  short FERTIG
          sub     al, 30h             ; ASCII nach Integer wandeln
          cmp     al, 9               ;  Wert größer als neun ?
          jg  FEHLER                  ; keine Ziffer = Fehler !
          mov     es:[di], al         ; Wert retten
          add     di, 4               ; Rett-Zeiger erhöhen
          dec     cl                  ; nächsten ASCII
          jnz HOLASC                  ;  schon alle zehn ASCII's ?
;─────────────────────────────────────────────────────────────────────────────
FERTIG:   mov     ax, @DATA
          mov     ds, ax
;-------------------------------------
          mov     al, ANZ
          mov     dh, al              ; Anzahl Ziffern retten für addieren
          dec     al                  ; -1 = Anzahl der Multiplikationen * 10
          mov     cl, al              ; Anzahl Ziffern retten
          mov     dl, al              ; Anzahl Ziffern retten
          jz  short ZUSAM             ; keine Multiplikationen, eine Ziffer !
;─────────────────────────────────────────────────────────────────────────────
          mov     di, OFFSET DEZ
;-------------------------------------
MALASC:   mov     eax, [di]           ; Wert holen
          mov     ebx, eax
          shl     eax, 3              ; Wert mal 8
          add     ebx, ebx            ; Wert mal 2
          add     eax, ebx
          dec     cl                  ;  letzte Multiplikation ?
          mov     [di], eax           ; Wert retten
          jnz MALASC
;---------------------------
          add     di, 4               ; Zeiger auf nächste Wert
          dec     dl                  ; Anzahl der Ziffern verringern
          mov     cl, dl
          jnz MALASC
;─────────────────────────────────────────────────────────────────────────────
ZUSAM:    xor     eax, eax
          mov     si, OFFSET DEZ      ; alle Werte zusammen rechnen
;-------------------------------------
PLUS:     add     eax, [si]
          add     si, 4
          dec     dh
          jnz PLUS
;─────────────────────────────────────────────────────────────────────────────
          mov     di, OFFSET ASCII    ; Doppel-Word nach Hex-Ziffern wandeln
          mov     cl, 8               ; 8 Ziffern
;-------------------------------------
A:        rol     eax, 4              ; 1 Nibble weiter
          mov     bl, al
          and     bl, 0Fh             ; nur low-Nibble
          add     bl, 30h             ; nach ASCII wandeln
          cmp     bl, 39h             ;  größer als Ziffer neun ?
          jna short B
          add     bl, 7               ; dann Buchstabe von "A" bis "F"
B:        mov     [di], bl            ; ASCII retten
          inc     di                  ; Zeiger erhöhen
          dec     cl                  ; Ziffer-Anzahl verringern
          jnz A
;─────────────────────────────────────────────────────────────────────────────
          mov     si, OFFSET ASCII-1  ; erste(n) Null(en) überlesen
          mov     dx, si
          inc     dx
;-------------------------------------
NULL:     inc     si
          cmp    BYTE PTR[si], "0"
          jz  NULL
;---------------------------
          sub     si, 0Ah
          cmp     si, dx
          jz  short AUSGABE           ; keine null vorhanden !
          add     si, 0Ah
          mov     dx, si
;-------------------------------------
AUSGABE:  mov     ah, 9               ; HEX ausgeben
          int   21h
;─────────────────────────────────────────────────────────────────────────────
          xor     al, al
DOS:      mov     ah, 4Ch             ; Dos-Rücksprung
          sti                         ; alle IRQ's wieder erlauben
          int   21h
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;----------------------------------------------------------------------------
FEHLER:   mov     ax, @DATA           ; Fehler-Text ausgeben,
          mov     ds, ax
;-------------------------------------
          mov     dx, OFFSET SYNTAX
          mov     ah, 9
          int   21h
          mov     al, 1
          jmp  short DOS              ; Programm beenden !
;─────────────────────────────────────────────────────────────────────────────
;                        D a t e n  -  S e g m e n t
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;----------------------------------------------------------------------------
.DATA
 ORG 0
;-------------------------------------
DEZ       DB 0,0,0,0                  ;  1. Ziffer
          DB 0,0,0,0                  ;  2. Ziffer
          DB 0,0,0,0                  ;  3. Ziffer
          DB 0,0,0,0                  ;  4. Ziffer
          DB 0,0,0,0                  ;  5. Ziffer
          DB 0,0,0,0                  ;  6. Ziffer
          DB 0,0,0,0                  ;  7. Ziffer
          DB 0,0,0,0                  ;  8. Ziffer
          DB 0,0,0,0                  ;  9. Ziffer
          DB 0,0,0,0                  ; 10. Ziffer
;-------------------------------------
ANZ       DB ?,0,0,0
;-------------------------------------
ASCII     DB "00000000", "$"          ; Hexadezimale ASCII's
;-----------------------------------------------------------------
SYNTAX    DB 0Dh,0Ah                  ; Carriage Return, Line-Feed
DB "╔══════════════════════════════════════════════════════════════════════════════╗"
DB "║                                                                              ║"
DB "║           SYNTAX:                 DEZ2HEX.exe Dezimal-Wert                   ║"
DB "║                                                                              ║"
DB "║                     Dezimal-Wert:  von  0  bis  4.294.967.295 (Doppel-Word)  ║"
DB "║                                                                              ║"
DB "║                            Die Trenn-Punkte dienen nur zur Übersicht,        ║"
DB "║                                                                              ║"
DB "║                              und dürfen nicht mit angegeben werden !         ║"
DB "║                                                                              ║"
DB "╚══════════════════════════════════════════════════════════════════════════════╝"
DB 7,"$"                              ; Bell, Ausgabe-Ende
;─────────────────────────────────────────────────────────────────────────────
.STACK 10h
 END

Code: Alles auswählen

;╔═════════════════════════════════════════════════════════════════════════════════════════╗
;║                                                                                         ║
;║  DEZ2BIT wandelt einen ganzahligen dezimalen Wert zu einer Bitfolge und gibt diese aus  ║
;║                                                                                         ║
;╚═════════════════════════════════════════════════════════════════════════════════════════╝
.MODEL SMALL
.386
.CODE
 ORG 100h
START:    mov     ax, @DATA
          mov     ds, ax
          mov     es, ax
          mov     di, OFFSET DEZ      ; Ziel-OFFSET der Integer-Werte
          mov     bp, OFFSET ANZ
;─────────────────────────────────────────────────────────────────────────────
          mov     ah, 62h             ; Segment des PSP's ermitteln
          int   21h
          cli                         ; alle IRQ's verhindern
          mov     ds, bx              ; PSP-Segment nach DS
;-------------------------------------
          mov     si, 80h             ; Zeiger auf Parameter (Kommando-Zeile)
          mov     al, [si]            ; Anzahl der ASCII's holen, ohne CR(0Dh)
          cmp     al, 2               ;  weniger als  2 ASCII's ?
          jb  FEHLER                  ; zu wenig = Fehler !
          cmp     al, 0Bh             ;  mehr    als 11 ASCII's ?
          ja  FEHLER                  ; zu viel  = Fehler !
          dec     al
          add     si, 2               ; Zeiger auf 1.ASCII hinter dem Space
          mov     es:[bp], al
;─────────────────────────────────────────────────────────────────────────────
;   Holt dezimale ASCII-Ziffer, wandelt max. 10 Ziffern und rettet die Werte
;─────────────────────────────────────────────────────────────────────────────
          mov     cl, 0Ah             ; Anzahl Ziffern
;-------------------------------------
HOLASC:   mov     al, [si]            ; ein ASCII aus PSP holen
          inc     si                  ; PSP-Zeiger erhöhen
          cmp     al, 0Dh             ;  schon Parameter-Ende (CR) ?
          jz  short FERTIG
          sub     al, 30h             ; ASCII nach Integer wandeln
          cmp     al, 9               ;  Wert größer als neun ?
          jg  FEHLER                  ; keine Ziffer = Fehler !
          mov     es:[di], al         ; Wert retten
          add     di, 4               ; Rett-Zeiger erhöhen
          dec     cl                  ; nächsten ASCII
          jnz HOLASC                  ;  schon alle zehn ASCII's ?
;─────────────────────────────────────────────────────────────────────────────
FERTIG:   mov     ax, @DATA
          mov     ds, ax
;-------------------------------------
          mov     al, ANZ
          mov     dh, al              ; Anzahl Ziffern retten für addieren
          dec     al                  ; -1 = Anzahl der Multiplikationen * 10
          mov     cl, al              ; Anzahl Ziffern retten
          mov     dl, al              ; Anzahl Ziffern retten
          jz  short ZUSAM             ; keine Multiplikationen, eine Ziffer !
;─────────────────────────────────────────────────────────────────────────────
          mov     di, OFFSET DEZ
;-------------------------------------
MALASC:   mov     eax, [di]           ; Wert holen
          mov     ebx, eax
          shl     eax, 3              ; Wert mal 8
          add     ebx, ebx            ; Wert mal 2
          add     eax, ebx
          dec     cl                  ;  letzte Multiplikation ?
          mov     [di], eax           ; Wert retten
          jnz MALASC
;---------------------------
          add     di, 4               ; Zeiger auf nächste Wert
          dec     dl                  ; Anzahl der Ziffern verringern
          mov     cl, dl
          jnz MALASC
;─────────────────────────────────────────────────────────────────────────────
ZUSAM:    mov     si, OFFSET DEZ      ; alle Werte zusammen rechnen
          xor     ebx, ebx
;-------------------------------------
PLUS:     add     ebx, [si]
          add     si, 4
          dec     dh
          jnz PLUS
;─────────────────────────────────────────────────────────────────────────────
          mov     dx, OFFSET KAST1
          mov     ah, 9
          int   21h
          mov     ah, 0Eh
          mov     al, "│"             ; Anfang
          int   10h
          mov     cl, 20h             ; 32 Bit
;-----------------------------
BIT:      rol     ebx, 1
          cmp     cl, 8               ;  1.Byte ?
          jz  short ACHT
          cmp     cl, 10h             ;  2.Byte ?
          jz  short ACHT
          cmp     cl, 18h             ;  3.Byte ?
          jz  short ACHT
ANALYS:   mov     al, bl
          and     al, 1               ;  Bit gesetzt ?
          jz  short LEER
          mov     al, "1"             ; gesetzt
GEBAUS:   int   10h
          dec     cl
          jnz BIT
;-----------------------------
          mov     al, "│"             ; Ende
          int   10h
          mov     dx, OFFSET KAST2
          mov     ah, 9
          int   21h
          jmp  short DOS
;-------------------------------------
 org START + ((($-START)/16)*16) + 16
;-------------------------------------
LEER:     mov     al, "0"             ; nicht gesetzt
          jmp  short GEBAUS
;-------------------------------------
 org START + ((($-START)/16)*16) + 16
;-------------------------------------
ACHT:     mov     al, "│"             ; Byte wird getrennt
          int   10h
          jmp  short ANALYS
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
DOS:      mov     ah, 4Ch             ; Dos-Rücksprung
          sti
          int   21h
;-----------------------------------------------------------------------------
FEHLER:   mov     ax, @DATA
          mov     ds, ax
          mov     dx, OFFSET SYNTAX
          mov     ah, 9
          int   21h
          jmp  short DOS
;─────────────────────────────────────────────────────────────────────────────
;                           D a t e n  -  S e g m e n t
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/32)*32) + 32
;---------------------------------------------------------------------------
.DATA
 ORG 0
;-------------------------------------
DEZ       DB 0,0,0,0                  ;  1. Ziffer
          DB 0,0,0,0                  ;  2. Ziffer
          DB 0,0,0,0                  ;  3. Ziffer
          DB 0,0,0,0                  ;  4. Ziffer
          DB 0,0,0,0                  ;  5. Ziffer
          DB 0,0,0,0                  ;  6. Ziffer
          DB 0,0,0,0                  ;  7. Ziffer
          DB 0,0,0,0                  ;  8. Ziffer
          DB 0,0,0,0                  ;  9. Ziffer
          DB 0,0,0,0                  ; 10. Ziffer
;-------------------------------------
ANZ       DB ?,0,0,0
;-----------------------------
KAST1     DB "┌────────┬────────┬────────┬────────┐",0Dh,0Ah,"$"
KAST2     DB 0Dh,0Ah,"└────────┴────────┴────────┴────────┘","$"
;-----------------------------
SYNTAX    DB 0Dh,0Ah
DB "╔══════════════════════════════════════════════════════════════════════════════╗"
DB "║                                                                              ║"
DB "║           SYNTAX:                 DEZ2BIT.exe Dezimal-Wert                   ║"
DB "║                                                                              ║"
DB "║                     Dezimal-Wert:  von  0  bis  4.294.967.295 (Doppel-Word)  ║"
DB "║                                                                              ║"
DB "║                            Die Trenn-Punkte dienen nur zur Übersicht,        ║"
DB "║                                                                              ║"
DB "║                              und dürfen nicht mit angegeben werden !         ║"
DB "║                                                                              ║"
DB "╚══════════════════════════════════════════════════════════════════════════════╝"
DB 7, "$"
;─────────────────────────────────────────────────────────────────────────────
.STACK 10h
 END

Code: Alles auswählen

;╔═════════════════════════════════════════════════════════════════════════════════════╗
;║                                                                                     ║
;║  HEX2DEZ wandelt einen hexadezimalen Wert zu einem dezimalen Wert und gibt ihn aus  ║
;║                                                                                     ║
;╚═════════════════════════════════════════════════════════════════════════════════════╝
.MODEL SMALL
.386
.CODE
 ORG 100h
START:    mov     ah, 62h             ; Segment des PSP's ermitteln
          int   21h
          cli                         ; Interrupt's verbieten
          mov     ds, bx              ; PSP-Segment nach DS
          mov     si, 80h             ; Zeiger auf Parameter
          mov     al, [si]            ; ASCII-Anzahl holen, ohne CR (0Dh)
          cmp     al, 2               ;  weniger als 2 ASCII's ?
          jb  FEHLER                  ; zu wenig = Fehler !
          cmp     al, 9               ;  mehr    als 9 ASCII's ?
          ja  FEHLER                  ; zu viel  = Fehler !
          add     si, 2               ; Zeiger auf ersten ASCII hinter SPACE
;─────────────────────────────────────────────────────────────────────────────
;            Holt Hex-ASCII-Ziffer, wandelt max. 8 Ziffern nach EAX
;─────────────────────────────────────────────────────────────────────────────
          xor     eax, eax            ; EAX löschen
          mov     cl, 8               ; max. acht hexadezimale ASCII's
;-------------------------------------
HOLASC:   mov     bl, [si]            ; ASCII holen
          inc     si                  ; Zeiger erhöhen
          sub     bl, 30h             ; ASCII nach Integer wandeln
          cmp     bl, 0Ah             ;  Wert kleiner als Zehn ?
          jb  short ZAHL              ; ja Wert von 0 bis 9
          cmp     bl, 11h             ;  Wert kleiner als großes "A" ?
          jb  FEHLER                  ; keine Ziffer = Fehler !
          cmp     bl, 17h             ;  Wert kleiner als großes "G" ?
          jb  short BUCH              ; ja Wert zwischen großem "A" bis "F"
          cmp     bl, 31h             ;  Wert kleiner als kleines "a" ?
          jb  short FEHLER            ; keine Ziffer = Fehler !
          cmp     bl, 36h             ;  Wert größer als kleines "f" ?
          ja  short FEHLER            ; keine Ziffer = Fehler !
          sub     bl, 20h             ; Klein-Buchstabe nach Groß-Buchstabe,
BUCH:     sub     bl, 7               ; Groß -Buchstabe nach Hex wandeln
ZAHL:     or      al, bl              ; Wert mit high-Nibble verknüpfen
          cmp    BYTE PTR[si], 0Dh    ;  Carriage Return = Parameter-Ende ?
          jz  short PAREND            ; ja zum auswerten
          shl     eax, 4              ; 4 Bit schieben = 1 Nibble
          dec     cl                  ; Zähler verringern
          jnz HOLASC                  ;  schon alle ASCII's ?
;─────────────────────────────────────────────────────────────────────────────
;     EAX nach zehn dezimalen ASCII's wandeln und im Daten-Bereich ablegen
;─────────────────────────────────────────────────────────────────────────────
PAREND:   mov     bx, @DATA
          mov     ds, bx
          mov     di, OFFSET ASCII
;-------------------------------------
          mov     cl, 0Ah             ; Zehn dezimale ASCII's
          mov     ebx, 1000000000
WANDEL:   xor     edx, edx
          div     ebx
          add     al, 30h             ; nach ASCII wandeln
          mov     esi, edx            ; Rest retten
          mov     [di], al            ; Ziffer retten
          inc     di                  ; Zeiger erhöhen
          mov     eax, ebx
          mov     ebx, 0Ah
          xor     edx, edx
          div     ebx
          mov     ebx, eax
          mov     eax, esi
          dec     cl
          jnz WANDEL
;-----------------------------------------------------------------------------
          mov     si, OFFSET ASCII-1  ; erste(n) Null(en) überlesen
          mov     dx, si
          inc     dx
NULL:     inc     si
          cmp    BYTE PTR[si], "0"
          jz  NULL
          sub     si, 0Ah
          cmp     si, dx
          jz  short AUSG               ; keine null vorhanden !
          add     si, 0Ah
          mov     dx, si
;-------------------------------------
AUSG:     mov     ah, 9               ; dezimale Zahl ausgeben
          int   21h
;-----------------------------------------------------------------------------
DOS:      mov     ah, 4Ch             ; Dos-Rücksprung
          sti
          int   21h
;-----------------------------------------------------------------------------
 org START + ((($-START)/16)*16) + 16
;----------------------------------------------------------------------------
FEHLER:   mov     ax, @DATA
          mov     ds, ax
          mov     dx, OFFSET SYNTAX
          mov     ah, 9
          int   21h
          jmp  short DOS
;─────────────────────────────────────────────────────────────────────────────
;                        D a t e n  -  S e g m e n t
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/32)*32) + 32
;----------------------------------------------------------------------------
.DATA
 ORG 0
SYNTAX    DB 0Dh, 0Ah
DB "╔══════════════════════════════════════════════════════════════════════════════╗"
DB "║                                                                              ║"
DB "║           SYNTAX:                HEX2DEZ.exe Hexadezimal-Wert                ║"
DB "║                                                                              ║"
DB "║             Hexadezimal-Wert:  von  0  bis  FFFFFFFF (Doppel-Word)           ║"
DB "║                                                                              ║"
DB "║                    je Ziffer:  von  0  bis  9  und  von  A  bis  F           ║"
DB "║                                                                              ║"
DB "║                      A bis F:  kann groß oder klein geschrieben werden       ║"
DB "║                                                                              ║"
DB "╚══════════════════════════════════════════════════════════════════════════════╝"
          DB 7, "$"
;-----------------------------------------------------------------------------
ASCII     DB "0000000000", "$"
;─────────────────────────────────────────────────────────────────────────────
.STACK 10h
 END

Code: Alles auswählen

;╔═════════════════════════════════════════════════════════════════════════════════╗
;║                                                                                 ║
;║  HEX2BIT wandelt einen hexadezimalen Wert zu einer Bitfolge und gibt diese aus  ║
;║                                                                                 ║
;╚═════════════════════════════════════════════════════════════════════════════════╝
.MODEL SMALL
.386
.CODE
 ORG 100h
START:    mov     ah, 62h             ; Segment des PSP's ermitteln
          int   21h
          cli                         ; Interrupt's verbieten
          mov     ds, bx              ; PSP-Segment nach DS
          mov     si, 80h             ; Zeiger auf Parameter
          mov     al, [si]            ; ASCII-Anzahl holen, ohne CR (0Dh)
          cmp     al, 2               ;  weniger als 2 ASCII's ?
          jb  FEHLER                  ; zu wenig = Fehler !
          cmp     al, 9               ;  mehr    als 9 ASCII's ?
          ja  FEHLER                  ; zu viel  = Fehler !
          add     si, 2               ; Zeiger auf ersten ASCII hinter SPACE
;─────────────────────────────────────────────────────────────────────────────
;            Holt Hex-ASCII-Ziffer, wandelt max. 8 Ziffern nach EAX
;─────────────────────────────────────────────────────────────────────────────
          xor     eax, eax            ; EAX löschen
          mov     cl, 8               ; max. acht hexadezimale ASCII's
;-------------------------------------
HOLASC:   mov     bl, [si]            ; ASCII holen
          inc     si                  ; Zeiger erhöhen
          sub     bl, 30h             ; ASCII nach Integer wandeln
          cmp     bl, 0Ah             ;  Wert kleiner als Zehn ?
          jb  short ZAHL              ; ja Wert von 0 bis 9
          cmp     bl, 11h             ;  Wert kleiner als großes "A" ?
          jb  FEHLER                  ; keine Ziffer = Fehler !
          cmp     bl, 17h             ;  Wert kleiner als großes "G" ?
          jb  short BUCH              ; ja Wert zwischen großem "A" bis "F"
          cmp     bl, 31h             ;  Wert kleiner als kleines "a" ?
          jb  FEHLER                  ; keine Ziffer = Fehler !
          cmp     bl, 36h             ;  Wert größer als kleines "f" ?
          ja  FEHLER                  ; keine Ziffer = Fehler !
          sub     bl, 20h             ; Klein-Buchstabe nach Groß-Buchstabe,
BUCH:     sub     bl, 7               ; Groß -Buchstabe nach Hex wandeln
ZAHL:     or      al, bl              ; Wert mit high-Nibble verknüpfen
          cmp    BYTE PTR[si], 0Dh    ;  Carriage Return = Parameter-Ende ?
          jz  short PAREND            ; ja zum auswerten
          shl     eax, 4              ; 4 Bit schieben = 1 Nibble
          dec     cl                  ; Zähler verringern
          jnz HOLASC                  ;  schon alle ASCII's ?
;─────────────────────────────────────────────────────────────────────────────
PAREND:   mov     ebx, eax
;-----------------------------
          mov     ax, @DATA
          mov     ds, ax
          mov     dx, OFFSET KAST1
          mov     ah, 9
          int   21h
          mov     ah, 0Eh
          mov     al, "│"             ; Anfang
          int   10h
          mov     cl, 20h             ; 32 Bit
;-----------------------------
BIT:      rol     ebx, 1
          cmp     cl, 8               ;  1.Byte ?
          jz  short ACHT
          cmp     cl, 10h             ;  2.Byte ?
          jz  short ACHT
          cmp     cl, 18h             ;  3.Byte ?
          jz  short ACHT
ANALYS:   mov     al, bl
          and     al, 1               ;  Bit gesetzt ?
          jz  short LEER
          mov     al, "1"             ; gesetzt
GEBAUS:   int   10h
          dec     cl
          jnz BIT
;-----------------------------
          mov     al, "│"             ; Ende
          int   10h
          mov     dx, OFFSET KAST2
          mov     ah, 9
          int   21h
          jmp  short DOS
;----------------------------------------------------------------------------
 org START + ((($-START)/16)*16) + 16
;-------------------------------------
LEER:     mov     al, "0"             ; nicht gesetzt
          jmp  short GEBAUS
;-------------------------------------
 org START + ((($-START)/16)*16) + 16
;-------------------------------------
ACHT:     mov     al, "│"             ; Byte wird getrennt
          int   10h
          jmp  short ANALYS
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;----------------------------------------------------------------------------
DOS:      mov     ah, 4Ch             ; Dos-Rücksprung
          sti
          int   21h
;-----------------------------------------------------------------------------
FEHLER:   mov     ax, @DATA
          mov     ds, ax
          mov     dx, OFFSET SYNTAX
          mov     ah, 9
          int   21h
          jmp  short DOS
;─────────────────────────────────────────────────────────────────────────────
;                           D a t e n  -  S e g m e n t
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/32)*32) + 32
;----------------------------------------------------------------------------
.DATA
 ORG 0
SYNTAX    DB 0Dh, 0Ah
DB "╔══════════════════════════════════════════════════════════════════════════════╗"
DB "║                                                                              ║"
DB "║           SYNTAX:                HEX2BIT.exe Hexadezimal-Wert                ║"
DB "║                                                                              ║"
DB "║             Hexadezimal-Wert:  von  0  bis  FFFFFFFF (Doppel-Word)           ║"
DB "║                                                                              ║"
DB "║                    je Ziffer:  von  0  bis  9  und  von  A  bis  F           ║"
DB "║                                                                              ║"
DB "║                      A bis F:  kann groß oder klein geschrieben werden       ║"
DB "║                                                                              ║"
DB "╚══════════════════════════════════════════════════════════════════════════════╝"
DB 7, "$"
;----------------------------------------------------------------------------
KAST1     DB "┌────────┬────────┬────────┬────────┐", 0Dh, 0Ah, "$"
KAST2     DB 0Dh, 0Ah, "└────────┴────────┴────────┴────────┘", "$"
;─────────────────────────────────────────────────────────────────────────────
.STACK 10h
 END
Alle vier dieser kleinen Programme kann man zusammen mit ihrem hier aufgelisteten Quellcode von meiner Homepage herunterladen: http://www.alice-dsl.net/freecracmaps/Tool/Zahlswap.zip

Dirk
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Codeschnipsel

Beitrag von freecrac »

Interne COMMAND.COM-Befehle ausführen
Ich habe in diesem Beipiel nur einige der interne DOS-Befehle aufgelistet um zu zeigen wie man diese aus einer Anwendung heraus ausführt.
Bei einigen dieser internen DOS-Befehle fehlen noch die Argumente so z.B bei "md" der Name des neu anzulegenden Verzeichnisses.
Diese Argumente müseen also ggf. noch angehängt bzw. im Datenbereich eingefügt werden.

Code: Alles auswählen

.MODEL SMALL
.386
  CODE SEGMENT use16 'CODE'
 assume cs:CODE,ds:DATEN,ss:STAPEL
 org 100h

START:    mov      ax, DATEN
          mov      ds, ax
          mov      si, OFFSET I17     ; Zeiger auf "SET" -Befehl
          int    2Eh                  ; internen COMMAND.COM-Befehl ausführen

          mov      ax, 4C00h          ; Dos-Rücksprung, Programm-Ende
          int    21h
  CODE ends
;---------------------------------------------------------------------------
  DATEN SEGMENT use32 'DATA'

I00   DB 8, "break on"
      DB 0Dh

I01   DB 14h, "call c:\mem_info.bat"
      DB 0Dh

I02   DB 4, "chcp"
      DB 0Dh

I03   DB 2, "cd .."
      DB 0Dh

I04   DB 3, "cls"
      DB 0Dh

I05   DB 12h, "copy a:\*.* c:\*.*"
      DB 0Dh

I06   DB 4, "ctty"
      DB 0Dh

I07   DB 4, "date"
      DB 0Dh

I08   DB 8, "del *.tmp"
      DB 0Dh

I09   DB 6, "dir /w"
      DB 0Dh

I0A   DB 9, "@echo off"
      DB 0Dh

I0B   DB 4, "exit"
      DB 0Dh

I0C   DB 3, "for %1 in ()"
      DB 0Dh

I0D   DB 4, "goto ende"
      DB 0Dh

I0E   DB 2, "if %a==%b"
      DB 0Dh

I0F   DB 2, "lh"
      DB 0Dh

I10   DB 2, "md"
      DB 0Dh

I11   DB 4, "path"
      DB 0Dh

I12   DB 5, "pause"
      DB 0Dh

I13   DB 6, "prompt"
      DB 0Dh

I14   DB 3, "rem"
      DB 0Dh

I15   DB 3, "ren"
      DB 0Dh

I16   DB 2, "rd"
      DB 0Dh

I17   DB 3, "set"
      DB 0Dh

I18   DB 5, "shift"
      DB 0Dh

I19   DB 4, "time"
      DB 0Dh

I1A   DB 4, "type"
      DB 0Dh

I1B   DB 3, "ver"
      DB 0Dh

I1C   DB 6, "verify"
      DB 0Dh

I1D   DB 3, "vol"
      DB 0Dh
  DATEN ends
;---------------------------------------------------------------------------
  STAPEL SEGMENT use16 STACK 'STACK'
       DB 10h dup (?)
  STAPEL ends
 end
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: Codeschnipsel

Beitrag von oDOSseus »

Ich hätte hier 3 Prozeduren zum Thema strings. Sind natürlich nur einfache, die den C-Funktionen strcmp, strncmp und strlen entsprechen. Es kommen aber noch welche dazu. Ich habe die Assembler-Funktionen dokumentiert, sodass sie verständlich sein sollten. Der unterschied zu den C-Funktionen ist, dass bei strcmp und strncmp nicht zurückgegeben wird, welcher Buchstabe größer oder kleiner ist, weil es wahrscheinlich in dem Leben eines Programmierers nur einmal vorkommt, dass man das wissen muss.

hier der ASM-Code:

Code: Alles auswählen

.MODEL TINY

;EQU-Table
END_OF_STR     EQU   24h ;End of string

.CODE
        org   0100h
START:
        lea   SI,   string1
        lea   DI,   string2

;;;COMPARE WHOLE STRINGS
        call  strcmp
        cmp   AL,   0FFh
        je    l1

        lea   DX,   msgFalse1
        jmp   l2
l1:     lea   DX,   msgTrue1
        
l2:     mov   AH,   09h
        int   21h
;;;COMPARE FIRST FOUR CHARS
l3:     mov   CX,   04h
        call  strncmp
        cmp   AL,   0FFh
        je    l4

        lea   DX,   msgFalse2
        jmp   l5
l4:     lea   DX,   msgTrue2

l5:     mov   AH,   09h
        int   21h

;;;CALC STRLEN OF STRING1
l6:
        call  strlen
        add   CX,   3030h  ;Of cause bullshit for numbers greater 9
        mov   AH,   09h
        lea   DX,   msgLength
        int   21h
        mov   AH,   02h
        mov   DL,   CH
        int   21h
        mov   DL,   CL
        int   21h
        
;;;END!!
lEnd:   mov   AX,   4C00h
        int   21h

;+-----------------------------------------------------------+
;|+---------------------------------------------------------+|
;||This proc compares two strings. The strings have to be   ||
;||stored at DS:SI and DS:DI. If the strings are not equal  ||
;||AL will be 00h. If they are equal AL will be FFh. This   ||
;||proc compare the string byte by byte until a END_OF_STR  ||
;||appears.                                                 ||
;|+---------------------------------------------------------+|
;+-----------------------------------------------------------+
strcmp  PROC  NEAR

        push  DI
        push  SI

        dec   DI              ;Is needed for the inc-command in Lbl1

strcmpLbl1:
        inc   DI              ;get next byte in [DI]
        lodsb                 ;get next byte in AL
        cmp   [DI], AL
        jne   strcmpLbl2

        ;>>the bytes are equal
        cmp   AL,   END_OF_STR ;Value is defined at the beginning
        jne   strcmpLbl1

        ;>>the bytes are equal and '$'
        ;If we reach this point both string have to be qual
        jmp   strcmpLbl3      ;move to the end of this function

strcmpLbl2:
        mov   AL,   00h       ;00h means strings are not equal
        jmp   strcmpLbl4      
strcmpLbl3:
        mov   AL,   0FFh      ;FFh means strings are equal
strcmpLbl4:
        pop   SI
        pop   DI

        ret
strcmp  ENDP

;+-----------------------------------------------------------+
;|+---------------------------------------------------------+|
;||This proc detects the end of a string by searching for   ||
;||END_OF_STR. Therefore the string has to be placed at     ||
;||DS:SI. The length of the string will be returned in CX.  ||
;||This function may crash if there is nor END_OF_STR.      ||
;|+---------------------------------------------------------+|
;+-----------------------------------------------------------+
strlen  PROC  NEAR

        push  AX
        push  SI

        xor   CX,   CX          ;our counter has to be zero

strlenLbl1:
        lodsb                   ;load one char to AL
        cmp   AL,   END_OF_STR  ;compare the char to END_OF_STR
        je    strlenLbl2
        inc   CX                                           
        jmp   strlenLbl1

strlenLbl2:
        pop   SI
        pop   AX
        ret

strlen  ENDP


;+-----------------------------------------------------------+
;|+---------------------------------------------------------+|
;||This proc compares the first CX chars of two strings (   ||
;||stored in DS:SI and DS:DI). If they are equal AL will be ||
;||FFh and if not AL will be 00h. If an END_OF_STR appears  ||
;||before CX chars are read the proc stops and AL will      ||
;||indicate if the strings have different lengths (00h means||
;||that the lengths are different and FFh that they have the||
;||same length).                                            ||
;|+---------------------------------------------------------+|
;+-----------------------------------------------------------+
strncmp PROC  NEAR

        push  DI
        push  SI
        push  CX

        dec   DI              ;Is needed for the inc-command in Lbl1

strncmpLbl1:
        dec   CX              ;we check until CX is zero
        inc   DI              ;get next byte in [DI]
        lodsb                 ;get next byte in AL
        cmp   [DI], AL
        jne   strncmpLbl2

        ;>>the bytes are equal
        cmp   AL,   END_OF_STR ;Value is defined at the beginning
        je    strncmpLbl3      ;both have the same length

        ;>>the bytes are equal and the string is not at its end
        cmp   CX,   00h        ;if it is zero we will end
        je    strncmpLbl3      ;all chars are equal

        ;>>the bytes are equal and we have to go on
        jmp   strncmpLbl1

strncmpLbl2:
        mov   AL,   00h       ;00h means strings are not equal
        jmp   strncmpLbl4
strncmpLbl3:
        mov   AL,   0FFh      ;FFh means strings are equal
strncmpLbl4:
        pop   CX
        pop   SI
        pop   DI

        ret
strncmp ENDP



msgTrue1    db   "Strings are equal",13,10,"$"
msgFalse1   db   "Strings are not equal",13,10,"$"
msgTrue2    db   "Strings are partial equal",13,10,"$"
msgFalse2   db   "Strings are partial not equal",13,10,"$"
msgLength   db   "Length of string1: $"
string1     db   "ABCDEFG$"
string2     db   "ABCD$"


END START
        END

Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: Codeschnipsel

Beitrag von oDOSseus »

Hier eine routine mit der man double-words auf einer 16bin CPU teilen kann. Zum Verständnis empfehle ich stark http://dcla.rkhb.de/div.html

Code: Alles auswählen

;----------------------------------------------------------
;Teilt ein dword durch ein anderes. Der Dividend ist AX:BX (AX ist das höhere
;word) und der Divisor in CX:DX (CX ist das höhere word). Das Ergebnis ist in
;CX:DX und der Rest in AX:BX
div_dword:
   mov    [div_dword_dividend],    bx  ;dividend
   mov    [div_dword_dividend+2],  ax
   mov    [div_dword_divisor],     dx  ;divisor
   mov    [div_dword_divisor+2],   cx
   ;Retten unseres zukünftigen Zählers DI:SI
   push   di
   push   si
   ;Setzen der variablen für den Schleifen durchlauf
   xor    di,    di      ;Ergebnis-
   xor    si,    si      ;         Register (di:si)
   xor    bx,    bx      ;bitshift-
   xor    dx,    dx      ;         Puffer (bx:dx)
   mov    cx,    0x20    ;Wir machen dies einzeln für jedes bit
   
  div_dword_loop:
   ;Das oberste Bit vom dividenden hochziehen
   shl    word [div_dword_dividend],    1
   rcl    word [div_dword_dividend+2],  1
   ;nach cx:dx
   rcl    dx,    1
   rcl    bx,    1
   
   ;Nun überprüfen wir ob es teilbar, also größer ist
   cmp    word [div_dword_divisor+2],  bx      ;Das höhere word zuerst
   je     div_dword_low_check
   jc     div_dword_below
   jmp    div_dword_above
  div_dword_low_check:
   cmp    word [div_dword_divisor],    dx      ;Dann das tiefere word
   ja     div_dword_above
  div_dword_below:
   ;Es ist teilbar!!!!
   sub    dx,    word [div_dword_divisor]
   sbb    bx,    word [div_dword_divisor+2]
   stc
  div_dword_above:
   rcl    si,    1
   rcl    di,    1   
   loop   div_dword_loop
   
   mov    ax,    bx
   mov    bx,    dx
   mov    cx,    di
   mov    dx,    si
   pop    si
   pop    di
   ret
Antworten