Discussion:
*Exe Programm aus Assembler heraus ausführen /4bh
(zu alt für eine Antwort)
p***@web.de
2006-07-31 12:34:42 UTC
Permalink
Hallo,

ich will aus einem Assembler Programm mit der Funktion 4bh (21h) ein
(externes) Exe- Programm ausführen.

Womit ich im Moment Probleme habe, ist der Parameter Block, dessen
Offset in bx stehen muss.

Leider ist er nur in Englisch kommentiert, mein Englisch ist aber eher
schwach..


Offset Size Description

00 word when AL=1, segment of env. or zero if using parents env.
word when AL=3, segment of load point for overlay
02 dword when AL=1, pointer to cmd line at PSP 80h
word when AL=3, relocation factor for EXE overlay
06 dword pointer to default ~FCB~ passed at ~PSP~ 5Ch
0A dword pointer to default FCB passes at PSP 6Ch
0E dword value of program SS:SP
12 dword value of program CS:IP

(Quelle PCHelp 2.1, David Jurgens)


Wie genau müsste der parameter Block aussehen? Gibt es irgendein
(möglichst kleines/ einfach zu verstehendes/ deutsch kommentiertes
;-)) Beispiel, an dem ich die Funktion begreifen lernen kann?

Ich würde mich sehr freuen, wenn ihr mir weiterhelfen könntet.

MfG,

Niels
Herbert Kleebauer
2006-07-31 18:21:40 UTC
Permalink
Post by p***@web.de
Womit ich im Moment Probleme habe, ist der Parameter Block, dessen
Offset in bx stehen muss.
Ich kann dir nur empfehlen, dir das Buch "PC Intern" von
Michael Tischer zu besorgen.

AH = 4Bh
AL = 00h
ES:BX = FAR-Zeiger auf den Parameterblock
DS:DX = FAR-Zeiger auf den Puffer mit dem Dateinamen des Programms



- Der Parameterblock muß folgendes Format haben:

Byte 0-1: Segmentadresse des Environment-Blocks
Byte 2-3: Offsetadresse der Kommandoparameter
Byte 4-5: Segmentadresse der Kommandoparameter
Byte 6-7: Offsetadresse des ersten FCB
Byte 8-9: Segmentadresse des ersten FCB
Byte 10-11: Offsetadresse des zweiten FCB
Byte 12-13: Segmentadresse des zweiten FCB

- Wird als Segmentadresse des Environment-Blocks der Wert 0 übergeben, so verfügt das aufgerufene Programm über den gleichen Environment-Block wie das aufrufende Programm.
- Die Kommandoparameter müssen im Speicher in der Art gespeichert sein, daß zunächst die Anzahl der Zeichen in der Kommandozeile als Byte abgespeichert wird. Darauf folgen die einzelnen ASCII-Zeichen, die durch ein Carriage Return (ASCII-Code 13) beendet werden. Dieses Carriage Return wird allerdings bei der Anzahl der Zeichen nicht mitgezählt.

- Der erste übergebene FCB wird ab der Adresse 5Ch, der zweite ab der Adresse 6Ch in den PSP des aufgerufenen Programms kopiert. Entnimmt das aufgerufene Programm diesen beiden FCB keine Informationen, können beliebige Werte in die FCB-Felder im Parameterblock eingetragen werden.
- Nach dem Aufruf dieser Funktion sind alle Register bis auf das CS- und das IP-Register zerstört. Ihr Inhalt sollte deshalb vor dem Funktionsaufruf gespeichert werden, um ihn nach dem Funktionsaufruf restaurieren zu können.

- Das aufgerufene Programm verfügt über alle Handles, die auch dem aufrufenden Programm zur Verfügung stehen.
p***@web.de
2006-08-01 08:10:15 UTC
Permalink
Hallo

vielen Dank für die Antwort, Herbert.

Ich habe versucht das ganze einmal in einem Beispielprogramm
auszuprobieren. Ausgeführt werden soll das Programm tasm.exe mit der
Option " /?".
_________________________
.model tiny
.code
org 100h
start:
mov word ptr [offset xyz],cs
lea bx, hallo
lea dx, xy
mov ah, 4bh
xor al,al
int 21

hallo dw 0
dw [offset cmd]
xyz dw,?
dw -1,-1
dw -1,-1
cmd db 03," /?",13
xy db "C:\asm\tasm.exe",0
end start
______________________________

Assembliert habe ich das ganze mit "tasm", gelinkt mit "tlink /t" und
ausgeführt unter Freedos. Herausgekommen ist folgendes: "Invalid
opcode at 0118 027a 0246 0000....


Weiss jemand, wo der Fehler liegt?
Ich wäre froh, jemand könnte mir weiterhelfen,

MfG,
Niels
( Sorry, der code ist seh unsauber und schlecht, bin noch Assembler
Anfänger)
Herbert Kleebauer
2006-08-01 17:24:11 UTC
Permalink
Post by p***@web.de
_________________________
.model tiny
.code
org 100h
mov word ptr [offset xyz],cs
lea bx, hallo
lea dx, xy
mov ah, 4bh
xor al,al
int 21
hallo dw 0
dw [offset cmd]
xyz dw,?
dw -1,-1
dw -1,-1
cmd db 03," /?",13
xy db "C:\asm\tasm.exe",0
end start
______________________________
Assembliert habe ich das ganze mit "tasm", gelinkt mit "tlink /t" und
ausgeführt unter Freedos. Herausgekommen ist folgendes: "Invalid
opcode at 0118 027a 0246 0000....
Weiss jemand, wo der Fehler liegt?
Was soll dein Program nach dem int21 auch machen, es führt
den dahinter liegenden Datenbereich als Befehle aus. Kein
Wunder, daß das zu einem "Invalid opcode" führt.

Ein anderes Problem ist, daß das laufende com Programm den
gesamten Speicher (bzw. den größten freien Speicherblock)
zugewiesen bekommt. Wenn du den nicht benötigten Bereich
nicht wieder frei gibst, dürfte kaum genügend freier Speicher
vorhanden sein um ein externes Program auszuführen. Willst
du die Funktuion 4b nur mal ausprobieren oder willst du sie
tatsächlich benutzen um TASM zu starten. Im zweiten Fall
soltest du überlegen, ob nicht eine batch Datei wesentlich
einfacher wäre.

Ich hab die Fkt. 4b nur einmal benutzt als es um die Frage
ging, ob man von einem DOS com Program eine Windows Messagebox
aufrufen kann. Ich habe dazu aus dem com Programm heraus ein
Windows exe Programm geschrieben und dies dann mit 4b/int21
gestartet und anschließend wieder gelöscht:


@=$100

00000000: 00000100: b4 3c move.b #$3c,m0
00000002: 00000102: 31 c9 eor.w r2,r2
00000004: 00000104: ba 01aa move.w #fname,r1
00000007: 00000107: cd 21 trap #$21 ; Datei oeffnen (___.com)
00000009: 00000109: 72 56 bcs.b _110
0000000b: 0000010b: 89 c3 move.w r0,r3

0000000d: 0000010d: fc bclr.w #10,sr
0000000e: 0000010e: be 01c5 move.w #buf2,r5
00000011: 00000111: bf 0341 move.w #buf1,r6

00000014: 00000114: ac _10: move.b (r5.w)+-,r0
00000015: 00000115: 38 06 01c0 cmp.b r0,esc0
00000019: 00000119: 75 47 bne.b _20
0000001b: 0000011b: a4 move.b (r5.w)+-,(r6.w)+-{s1}
0000001c: 0000011c: 81 fe 0341 _100: cmp.w #buf1,r5
00000020: 00000120: 72 f2 blo.b _10
00000022: 00000122: b4 40 move.b #$40,m0
00000024: 00000124: ba 0341 move.w #buf1,r1
00000027: 00000127: 89 f9 move.w r6,r2
00000029: 00000129: 29 d1 sub.w r1,r2
0000002b: 0000012b: cd 21 trap #$21

0000002d: 0000012d: b4 3e move.b #$3e,m0
0000002f: 0000012f: cd 21 trap #$21

00000031: 00000131: b8 4a00 move.w #$4a00,r0 ; Speicher nach 64k freigeben
00000034: 00000134: bb 1000 move.w #$1000,r3
00000037: 00000137: cd 21 trap #$21

00000039: 00000139: b4 09 move.b #$09,m0 ; text ausgeben
0000003b: 0000013b: ba 0196 move.w #text,r1
0000003e: 0000013e: cd 21 trap #$21

00000040: 00000140: 8c d8 move.w s0,r0
00000042: 00000142: a3 01b6 move.w r0,p_seg
00000045: 00000145: a3 01ba move.w r0,p_f1
00000048: 00000148: a3 01be move.w r0,p_f2
0000004b: 0000014b: b8 4b00 move.w #$4b00,r0
0000004e: 0000014e: bb 01b2 move.w #par,r3
00000051: 00000151: ba 01aa move.w #fname,r1
00000054: 00000154: 1e move.w s0,-(sp)
00000055: 00000155: cd 21 trap #$21 ; ___.com starten
00000057: 00000157: 1f move.w (sp)+,s0


00000058: 00000158: b4 41 _120: move.b #$41,m0 ; ___.com loeschen
0000005a: 0000015a: ba 01aa move.w #fname,r1
0000005d: 0000015d: cd 21 trap #$21
0000005f: 0000015f: 72 f7 bcs.b _120 ; funktioniert erst, wenn ___.com beendet ist

00000061: 00000161: c3 _110: rts.w

00000062: 00000162: 3a 06 01c1 _20: cmp.b esc1,r0
00000066: 00000166: 75 05 bne.b _30
00000068: 00000168: 31 c0 eor.w r0,r0
0000006a: 0000016a: ab move.w r0,(r6.w)+-{s1}
0000006b: 0000016b: eb af br.b _100
0000006d: 0000016d: 3a 06 01c2 _30: cmp.b esc2,r0
00000071: 00000171: 75 06 bne.b _40
00000073: 00000173: 31 c0 eor.w r0,r0
00000075: 00000175: ab move.w r0,(r6.w)+-{s1}
00000076: 00000176: aa _31: move.b r0,(r6.w)+-{s1}
00000077: 00000177: eb a3 br.b _100
00000079: 00000179: 3a 06 01c3 _40: cmp.b esc3,r0
0000007d: 0000017d: 75 06 bne.b _50
0000007f: 0000017f: 31 c0 eor.w r0,r0
00000081: 00000181: ab move.w r0,(r6.w)+-{s1}
00000082: 00000182: ab move.w r0,(r6.w)+-{s1}
00000083: 00000183: eb 97 br.b _100
00000085: 00000185: 3a 06 01c4 _50: cmp.b esc4,r0
00000089: 00000189: 75 eb bne.b _31
0000008b: 0000018b: ac move.b (r5.w)+-,r0
0000008c: 0000018c: 0f b6 c8 movu.bw r0,r2
0000008f: 0000018f: 41 inc.w r2
00000090: 00000190: 31 c0 eor.w r0,r0
00000092: 00000192: f3 aa rep_r2 move.b r0,(r6.w)+-{s1}
00000094: 00000194: eb 86 br.b _100

00000096: 00000196: 63 6c 69 63 6b 20
0000009c: 0000019c: 74 68 65 20 6f 4b
000000a2: 000001a2: 20 62 75 74 74 6f
000000a8: 000001a8: 6e 24 text: dc.b "click the oK button$"
000000aa: 000001aa: 5f 5f 5f 2e 63 6f
000000b0: 000001b0: 6d 00 fname: dc.b "___.com",0
000000b2: 000001b2: 0000 par: dc.w 0
000000b4: 000001b4: 0080 dc.w $80
000000b6: 000001b6: 0000 P_seg: dc.w 0
000000b8: 000001b8: 005c dc.w $5c
000000ba: 000001ba: 0000 p_f1: dc.w 0
000000bc: 000001bc: 006c dc.w $6c
000000be: 000001be: 0000 p_f2: dc.w 0

esc:
esc0: blk.b 1 ; escape for esc0-esc4
esc1: blk.b 1 ; 2 0 bytes (esc1)
esc2: blk.b 1 ; 3 0 bytes (esc2)
esc3: blk.b 1 ; 3 0 bytes (esc3)
esc4: blk.b 1 ; n 0 bytes (esc4 n)

buf2: blk.b 385-5 ; ACHTUNG: richtig Laenge einsetzen
buf1:
Sebastian Biallas
2006-08-01 17:22:38 UTC
Permalink
Post by Herbert Kleebauer
@=$100
00000000: 00000100: b4 3c move.b #$3c,m0
Was sind denn das für krasse x86-Mnemonics? Ist ja noch eine Spur
ekelhafter als der AT&T-Style.
--
Gruß,
Sebastian
Herbert Kleebauer
2006-08-01 18:36:34 UTC
Permalink
Post by Sebastian Biallas
Post by Herbert Kleebauer
@=$100
00000000: 00000100: b4 3c move.b #$3c,m0
Was sind denn das für krasse x86-Mnemonics? Ist ja noch eine Spur
ekelhafter als der AT&T-Style.
Nicht jeder is so ein extremer Masochist, daß er bereit ist eine
derartig perverse Syntax zu verwenden wie sie von ein paar
Sadisten bei Intel erdacht wurde.
Sebastian Biallas
2006-08-01 18:41:43 UTC
Permalink
Post by Herbert Kleebauer
Post by Sebastian Biallas
Post by Herbert Kleebauer
@=$100
00000000: 00000100: b4 3c move.b #$3c,m0
Was sind denn das für krasse x86-Mnemonics? Ist ja noch eine Spur
ekelhafter als der AT&T-Style.
Nicht jeder is so ein extremer Masochist, daß er bereit ist eine
derartig perverse Syntax zu verwenden wie sie von ein paar
Sadisten bei Intel erdacht wurde.
Mag sein, beantwortet meine eigentliche Frage aber nicht: Wo kommt das
her? Sieht nach missbrauchtem 68000 aus.

Im Übringen mag die x86-Architektur zwar furchtbar sein, die
Intel-Syntax hat aber so ziemlich die lesbarsten Assembler-Mnemonics,
die ich kenne.
--
Gruß,
Sebastian
Herbert Kleebauer
2006-08-01 19:51:41 UTC
Permalink
Post by Sebastian Biallas
Mag sein, beantwortet meine eigentliche Frage aber nicht: Wo kommt das
In deinem letzten Posting war überhaupt keine Frage.
Post by Sebastian Biallas
her? Sieht nach missbrauchtem 68000 aus.
Was sollte daran "mißbraucht" sein? Die im Vergleich zum x86 wesentlich
"schönere" 68k Architektur gehört ja leider weitgehend der Vergangenheit
an. Aber immerhin kann man ja zumindest die logisch durchdachte 68k
Assemblersynatx (die ihren Ursprung wohl bei der PDP11 hat) beim x86
weiter verwenden (die Hardware muß man so hinnehmen wie sie ist, für
die Software gilt dies glücklicherweise nicht).
Post by Sebastian Biallas
Im Übringen mag die x86-Architektur zwar furchtbar sein, die
Intel-Syntax hat aber so ziemlich die lesbarsten Assembler-Mnemonics,
die ich kenne.
Genau anders herum. Seit dem 386 ist die Architektur ganz brauchbar
(war echt eine tolle Leistung was die Intel Leute aus dem 16 Bit x86
gemacht haben) nur bei der Assemblersyntax dreht es jedem logisch
Denkenden den Magen um.

mov ebx,eax; mov ecx,ebx; mov edx,ecx;

lege in den Umschlag den Brief; lege in die Sachtel den Umschlag; lege in den Safe die Schachtel;

Diese Zeile muß man fünf mal lesen um sie zu verstehen, jeder vernünftig
Mensch würde schreiben:

lege den Brief in den Umschlag; lege den Umschlag in die Schachtel; lege die Schachtel in den Safe;

move.l r0,r1; move.l r1,r2; move.l r2,r3;


Warum kann man nicht genau so wie den Speicheradressraum auch den
Registeradressraum einfach durchnummerieren? Warum benutzt man
so viele Namen (eax,ax,ah,al,ebx,bx,bh,bl,ecx,cx,ch,cl,edx,dx,dh,dl,
ebp,bp,esi,si,edi,di,esp,sp) anstatt einfach r0-r7 zu verwenden.
Glücklicherweise hat AMD die 64 Bit Erweiterung spezifiziert,
denn sonst würden wir vermutlich nochmals jede Menge Namen für
die restlichen Register haben.


Was bitte hat die Operandengröße (8, 16, 32 Bit) bei den Operanden
zu suchen? Eine 8 und eine 32 Bit Addition haben nun mal einen
unterschiedlichen Opcode, die Addressangabe unterscheidet sich dagegen
nicht. Es ist also völlig unlogisch zu schreiben:

inc byte ptr [adresse]

logisch ist:

inc.b adresse


Genau so unlogsch ist die unterschiedlich Indirektionsstufe im
Speicher- und im Registeradressraum.

Wenn ich die Zahl 5 in das Register eax schreiben will, kann ich
entweder "mov (eax),5" oder "move eax,#5" (oder wie bei GAS $5)
schreiben, aber sicherlich nicht "mov eax,5".

Und das läßt sich beliebig fortsetzen. Ich habe bisher überhaupt
noch nichts gefunden was bei der Intel Syntax auch nur annähernd
logisch ist. Und noch schlimmer wird es dann bei "High Level"
Assembleren wie MASM bei dem es dann auch noch Dinge wie PROC,
ENDPROC, ASSUME usw. gibt (von denen die CPU nun absolut keine
Ahnung hat).
Sebastian Biallas
2006-08-01 20:59:40 UTC
Permalink
Post by Herbert Kleebauer
Post by Sebastian Biallas
Mag sein, beantwortet meine eigentliche Frage aber nicht: Wo kommt das
In deinem letzten Posting war überhaupt keine Frage.
In <***@news.dfncis.de> steht: "Was sind denn das für krasse
x86-Mnemonics?"

Ich hab mich vielleicht etwas harsch ausgedrückt, aber die Frage war
durchaus echt gemeint.
Post by Herbert Kleebauer
Post by Sebastian Biallas
her? Sieht nach missbrauchtem 68000 aus.
Was sollte daran "mißbraucht" sein?
Dass die Schreibweise und Nomenklatur einer ganz anderen Architektur auf
x86 übertragen wird.
Post by Herbert Kleebauer
Die im Vergleich zum x86 wesentlich
"schönere" 68k Architektur gehört ja leider weitgehend der Vergangenheit
an. Aber immerhin kann man ja zumindest die logisch durchdachte 68k
Assemblersynatx (die ihren Ursprung wohl bei der PDP11 hat) beim x86
weiter verwenden (die Hardware muß man so hinnehmen wie sie ist, für
die Software gilt dies glücklicherweise nicht).
Dabei entstehen dann auch noch diverse Inkonsistenzen:
* cx ist eigentlich r1
* di ist eigentlich r7
* Es wird "vorgetäuscht", dass die Register omnipotent sind
Post by Herbert Kleebauer
Post by Sebastian Biallas
Im Übringen mag die x86-Architektur zwar furchtbar sein, die
Intel-Syntax hat aber so ziemlich die lesbarsten Assembler-Mnemonics,
die ich kenne.
Genau anders herum. Seit dem 386 ist die Architektur ganz brauchbar
(war echt eine tolle Leistung was die Intel Leute aus dem 16 Bit x86
gemacht haben) nur bei der Assemblersyntax dreht es jedem logisch
Denkenden den Magen um.
Ich würde mich schon als logisch denkenden Menschen bezeichnen, und bei
mir dreht sich der Magen nicht um.
Post by Herbert Kleebauer
mov ebx,eax; mov ecx,ebx; mov edx,ecx;
lege in den Umschlag den Brief; lege in die Sachtel den Umschlag; lege in den Safe die Schachtel;
Diese Zeile muß man fünf mal lesen um sie zu verstehen, jeder vernünftig
lege den Brief in den Umschlag; lege den Umschlag in die Schachtel; lege die Schachtel in den Safe;
move.l r0,r1; move.l r1,r2; move.l r2,r3;
Ich weiß jetzt nicht genau, was Du mir sagen willst.

Bei PowerPC heißt es auch (wenn man ihn nicht mit AT&T vergewaltigt)
mr r3, r0; mr r1, r3; mr r2, r1
analog zu
r3:=r0; r1:=r3; r2:=r1;
Post by Herbert Kleebauer
Warum kann man nicht genau so wie den Speicheradressraum auch den
Registeradressraum einfach durchnummerieren?
Weil die Register früher grundverschieden waren (an vielen Stellen sind
sich das ja immernoch). Mit x86_64 hätte man die Schreibweise aber
endlich mal ändern können. Beachte aber, dass bei "Deiner" Schreibweise
der Registerraum auch nicht konsequenz durchnummeriert wird.
Post by Herbert Kleebauer
Warum benutzt man
so viele Namen (eax,ax,ah,al,ebx,bx,bh,bl,ecx,cx,ch,cl,edx,dx,dh,dl,
ebp,bp,esi,si,edi,di,esp,sp) anstatt einfach r0-r7 zu verwenden.
Glücklicherweise hat AMD die 64 Bit Erweiterung spezifiziert,
denn sonst würden wir vermutlich nochmals jede Menge Namen für
die restlichen Register haben.
Leider waren sie dabei nicht konsequent. Gerade bei Macros für
Kryptocode nervt das. Kann man sich ja dann mit Assemblermacros
umdefinieren.
Post by Herbert Kleebauer
Was bitte hat die Operandengröße (8, 16, 32 Bit) bei den Operanden
zu suchen?
Warum nicht? Man operiert ja durchaus mit Teilregistern.
Post by Herbert Kleebauer
Eine 8 und eine 32 Bit Addition haben nun mal einen
unterschiedlichen Opcode, die Addressangabe unterscheidet sich dagegen
inc byte ptr [adresse]
inc.b adresse
Man benutzt gerade einen Assembler, damit der einem Arbeit abnimmt.

Unterscheidest Du zwischen:

83 c0 01 │ add eax,1
05 01 00 00 00 │ add eax,1
81 c0 01 00 00 00 │ add eax,1

Ich gehe davon aus, dass das der Assembler das für mich übernimmt.
Post by Herbert Kleebauer
Genau so unlogsch ist die unterschiedlich Indirektionsstufe im
Speicher- und im Registeradressraum.
Wenn ich die Zahl 5 in das Register eax schreiben will, kann ich
entweder "mov (eax),5" oder "move eax,#5" (oder wie bei GAS $5)
schreiben, aber sicherlich nicht "mov eax,5".
Warum? Viel dümmer finde ich in dem Zusammenhang, dass nicht unbedingt
klar ist, ob eax (oder r0) ein Symbol oder ein Register ist.
Post by Herbert Kleebauer
Und das läßt sich beliebig fortsetzen. Ich habe bisher überhaupt
noch nichts gefunden was bei der Intel Syntax auch nur annähernd
logisch ist. Und noch schlimmer wird es dann bei "High Level"
Assembleren wie MASM bei dem es dann auch noch Dinge wie PROC,
ENDPROC, ASSUME usw. gibt (von denen die CPU nun absolut keine
Ahnung hat).
Die CPU hat auch keine Ahnung von "move.b #$3c,m0". Deswegen
benutzt/braucht man ja Assembler.
--
Gruß,
Sebastian
Stefan Reuther
2006-08-02 16:45:38 UTC
Permalink
Post by Herbert Kleebauer
Post by Sebastian Biallas
Im Übringen mag die x86-Architektur zwar furchtbar sein, die
Intel-Syntax hat aber so ziemlich die lesbarsten Assembler-Mnemonics,
die ich kenne.
Genau anders herum. Seit dem 386 ist die Architektur ganz brauchbar
(war echt eine tolle Leistung was die Intel Leute aus dem 16 Bit x86
gemacht haben) nur bei der Assemblersyntax dreht es jedem logisch
Denkenden den Magen um.
mov ebx,eax; mov ecx,ebx; mov edx,ecx;
"Lade ebx mit eax, lade ecx mit ebx, lade edx mit ecx".

Vorgänger von x86 ist nun mal der 8080 / Z80, mit "ld bc,hl" usw.
Außerdem hat fast jede Programmiersprache die Zuweisungen in der
Reihenfolge "ziel := quelle".
Post by Herbert Kleebauer
Warum kann man nicht genau so wie den Speicheradressraum auch den
Registeradressraum einfach durchnummerieren? Warum benutzt man
so viele Namen (eax,ax,ah,al,ebx,bx,bh,bl,ecx,cx,ch,cl,edx,dx,dh,dl,
ebp,bp,esi,si,edi,di,esp,sp) anstatt einfach r0-r7 zu verwenden.
Weil die Registernamen eine Bedeutung haben und keinesfalls gleichwertig
sind. ax = *A*kkumulator, bx = *B*asisregister (für Adressierung und
xlat), cx = *C*ount register, dx = *D*ata, si = Source Index, di =
Destination index usw.

(Ganz besonders wunderbar finde ich ja deine Syntax für cli / sti mit
'bclr' und 'bset'. Was interessiert mich die Bitposition von dem Ding im
Flagregister?)
Post by Herbert Kleebauer
Was bitte hat die Operandengröße (8, 16, 32 Bit) bei den Operanden
zu suchen? Eine 8 und eine 32 Bit Addition haben nun mal einen
unterschiedlichen Opcode, die Addressangabe unterscheidet sich dagegen
inc byte ptr [adresse]
inc.b adresse
Zum einen kannst du in "höheren" Assemblern wie TASM oder MASM "inc
variablenname" schreiben (wozu die Operandengröße wiederholen, wenn man
dem Assembler schon gesagt hat, dass das ein Byte ist?).

Zum anderen drückt 'inc byte ptr [adresse]' sehr deutlich aus, dass auf
Speicher zugegriffen wird. Insbesondere in Fällen, wo adresse=ebx ist o.ä.

Ob man nun 'inc byte ptr' oder 'incb' oder meinetwegen 'inc.b' schreibt,
ist durchaus verhandelbar.
Post by Herbert Kleebauer
Genau so unlogsch ist die unterschiedlich Indirektionsstufe im
Speicher- und im Registeradressraum.
Wenn ich die Zahl 5 in das Register eax schreiben will, kann ich
entweder "mov (eax),5" oder
Das ist eindeutigst eine Indirektion.
Post by Herbert Kleebauer
"move eax,#5" (oder wie bei GAS $5)
schreiben, aber sicherlich nicht "mov eax,5".
Momentmal. Ich will die Zahl 5
5
in das Register eax
eax
schreiben. Der Befehl zum Schreiben lautet 'mov'. Alles zusammen also
mov eax,5
Perfekt logisch für mich.


Stefan
Heiko Nocon
2006-08-02 18:15:52 UTC
Permalink
Post by Stefan Reuther
Momentmal. Ich will die Zahl 5
5
in das Register eax
eax
schreiben. Der Befehl zum Schreiben lautet 'mov'. Alles zusammen also
mov eax,5
Perfekt logisch für mich.
Für mich nicht. Dieses konkrete Problem ist allerdings auch fast der
einzige Punkt, bei dem ich mit der Meinung von H.K. konform gehe. Die
Geschichte lea vs. mov zeigt, daß es hier tatsächlich einen
systemimmanenten logischen Konflikt gibt. Der andere Punkt, bei dem ich
seine Auffassung teile, ist die Notation der Operandenbreite. Es ist
einfach logischer, dies einheitlich beim Operator zu notieren. Damit
wird die Notation nämlich unabhängig von der Art der Operanden.

Seine Konventionen für die Registerbenamsung hingegen sind angesichts
der Tatsache sinnlos, daß die Register in der x86-Architektur eben
niemals universell austauschbar waren und es auch heute trotz aller
Fortschritte immer noch nicht sind.
Das waren sie allerdings auch bei seiner offensichtlichen
"Heimatarchitektur", den 68k nicht vollständig, was sich schon allein
durch die Unterscheidung von aX und dX dokumentiert. Darüber hinaus
waren nichtmal die Register einer Gruppe 100% austauschbar, a7 z.b.
spielte da durchaus auch eine Sonderrolle.
Und wenn ich mir andere Inkarnationen dieser Grundidee anschaue
(AVR-Assembler z.B) da könnte einem regelrecht schlecht werden, denn
auch hier gibt es massive Einschränkungen bei der Benutzung der
Register, die sich ihren Bezeichnungen nicht entnehmen läßt.
Insofern kann er sich seine gesamte diesbezügliche Argumentation also
getrost herzhaft in den Arsch schieben. Sinnvoll ist der Ansatz dann
(und nur dann!), wenn die Register tatsächlich ohne jede Einschränkung
frei austauschbar sind.

Seine Einlassungen bezüglich der Reihenfolge der Notation von Quelle und
Ziel sind gleich ganz für'n Garten. In den weitaus meisten synthetischen
Sprachen (das geht weit über die diversen Assemblersprachen hinaus)
werden Zuweisungsoperationen so notiert, daß das Ziel links und die
Quelle rechts steht.
Dirk Wolfgang Glomp
2006-08-03 02:15:30 UTC
Permalink
Post by Heiko Nocon
Seine Einlassungen bezüglich der Reihenfolge der Notation von Quelle und
Ziel sind gleich ganz für'n Garten. In den weitaus meisten synthetischen
Sprachen (das geht weit über die diversen Assemblersprachen hinaus)
werden Zuweisungsoperationen so notiert, daß das Ziel links und die
Quelle rechts steht.
Ist es beim AT-Syntax nicht umgekehrt?

Dirk
Stefan Reuther
2006-08-03 15:43:06 UTC
Permalink
Post by Heiko Nocon
Post by Stefan Reuther
Momentmal. Ich will die Zahl 5
5
in das Register eax
eax
schreiben. Der Befehl zum Schreiben lautet 'mov'. Alles zusammen also
mov eax,5
Perfekt logisch für mich.
Für mich nicht. Dieses konkrete Problem ist allerdings auch fast der
einzige Punkt, bei dem ich mit der Meinung von H.K. konform gehe. Die
Geschichte lea vs. mov zeigt, daß es hier tatsächlich einen
systemimmanenten logischen Konflikt gibt.
Das dürfte einfach deswegen ein Problem sein, weil die wichtigsten
Assembler eben zwischen
foo dw ?
mov ax, foo
und
foo equ 5
mov ax, foo
keinen syntaktischen Unterschied machen; der Assembler also
Typinformationen mitführen muss. Der unterschiedliche Opcode ist aus dem
Befehl selbst nicht erkennbar.

Im Disassemblat (und, war das nicht auch bei nasm so?) stehen dann
Speicheroperanden wieder gut erkennbar in Klammern.


Stefan
Dirk Wolfgang Glomp
2006-08-04 05:11:59 UTC
Permalink
Post by Stefan Reuther
Im Disassemblat (und, war das nicht auch bei nasm so?) stehen dann
Speicheroperanden wieder gut erkennbar in Klammern.
Ja NASM benötigt immer []-Klammer.

...

Bei MASM sind sie optional, wenn mit einem Register als
Ziel/Quelle der Speicherzugriff vollzogen wird.
Sonst muß mit BYTE/WORD/DWORD PTR die []-Klammer gesetzt werden,
um die Zugriffsart zu spezifizieren.

Benutzt man im ersten Fall keine Klammern, können beim Lesen des
Listings, Konstante mit Speicher-Referenzen leicht verwechselt werden.
Um dieses Problem abzumildern, werden von mir Konstante groß+klein,
Speicheradressen in reinen Großbuchstaben geschrieben,
oder besser immer die []-Klammer benutzt.

Dirk

Dirk Wolfgang Glomp
2006-08-01 17:38:33 UTC
Permalink
Post by Sebastian Biallas
Post by Herbert Kleebauer
@=$100
00000000: 00000100: b4 3c move.b #$3c,m0
Was sind denn das für krasse x86-Mnemonics? Ist ja noch eine Spur
ekelhafter als der AT&T-Style.
Herbert hat zum Glück wieder jeweils den Opcode mit angegeben.

Dirk
p***@web.de
2006-08-01 17:47:27 UTC
Permalink
Post by Herbert Kleebauer
Was soll dein Program nach dem int21 auch machen, es führt
den dahinter liegenden Datenbereich als Befehle aus. Kein
Wunder, daß das zu einem "Invalid opcode" führt.
Ein anderes Problem ist, daß das laufende com Programm den
gesamten Speicher (bzw. den größten freien Speicherblock)
zugewiesen bekommt. Wenn du den nicht benötigten Bereich
nicht wieder frei gibst, dürfte kaum genügend freier Speicher
vorhanden sein um ein externes Program auszuführen. Willst
du die Funktuion 4b nur mal ausprobieren oder willst du sie
tatsächlich benutzen um TASM zu starten. Im zweiten Fall
soltest du überlegen, ob nicht eine batch Datei wesentlich
einfacher wäre.
Ich hab die Fkt. 4b nur einmal benutzt als es um die Frage
ging, ob man von einem DOS com Program eine Windows Messagebox
aufrufen kann. Ich habe dazu aus dem com Programm heraus ein
Windows exe Programm geschrieben und dies dann mit 4b/int21
Hallo Herbert,

vielen Dank für die Hilfe.
-Das mit dem vergessenen int21:4ch ist peinlich....
Dann wäre dieses Problem geklärt.
- Zu dem zweiten Problem: Leider ist eine Batch Datei keine
Alternative...Ich programmiere gerade einen Companion DOS- Virus (nur
zu Versuchszwecken und nur auf meinem von der Außenwelt abgeschotteten
Zweitrechner) und da wäre eine Bat Datei auffällig.
D.h. in meinem Fall, dass der Virus den Commandline- Parameter
entgegennimmt und am Schluss der *.com (des Virus) die entsprechende
*.Exe Datei (mit den entgegengenommenen Kommandooptionen) aufruft . Der
Speicher, den die *.com Datei verwendet hat kann also komplett
freigegeben werden, Register müssten auch nicht gesichert werden.

Danke auf jeden Fall, ich arbeite mal den Beispieltext durch und schaue
ob ichs begreife.

MfG,

Niels
Loading...