Hallo, guten Tag.
Ich möchte bitte den X86 ASM kennenlernen.
Ich habe mir schon etwas Text dafür runtergeladen.
Aber wie ich eine grosse Adresse beschreibe um Byte/Word-Daten dahin zu
schreiben und zurückzuholen habe ich nicht gefunden.
CS,DS,SS,ES ???
Die Adresse $b8000 ist ja zu gross (CGA-Adresse) für meine Denkweise.
----------------------
mov ax,$fffF
mov [$b8000],ax
---------------------
Wie schreibe ich das bitte?
Danke.
Gruss
peter schrieb:> Ich spiele mit dem NASM.
Dann lerne die Sprache. Wenn man weiß, was man tut, macht das Spielen
viel mehr Spaß als wenn man vollblind im Nebel stochert...
Die Segmentierung beim x86 ist doch easy. Wenn es nur um eine Adresse
geht ist das Segmentregister Adresse/10h. In das normale Register kommen
die letzten vier Bits der Adresse. Also als Beispiel Adresse 12345h,
dann ist bei DS:SI DS=1234h und SI=0005h. Die gleiche Adresse wäre auch
DS=1000h und SI=2345h, je nachdem was man übersichtlicher findet.
Kurz gesagt 0000:0010 ist die gleiche Adresse wie 0001:0000.
DOS z.B. läd .COM-Dateien immer an eine Adresse xxxx:0100. Die xxxx sind
alle Segmentregister und die 0100h ist die Einsprungadresse in den Code.
0000h-0100h enthält die Umgebungsinformationen, z.B. die Kommandozeile.
Daher können .COM-Dateien maximal 64k-0100h Bytes groß sein und DOS
kümmert sich quasi um gar nichts.
.EXE-Dateien werden an CS:0000 geladen und die Datenregister DS und ES
sind um 10h niedriger initialisiert als CS. Dadurch findet man die
Umgebungsvariablen direkt ab DS:0000. DOS kann dabei mehr Code als
64kByte laden, den den Stack (SS:SP) passend setzen und eine beliebige
Einsprungadresse (CS:IP) anspringen. Diese Informationen finden sich im
Header der .EXE-Datei. Wenn Dein Code größer als 64kByte ist, mußt Du
Dich aber trotzdem selbst um die Codesegment-Anpassung kümmern, z.B.
durch far jumps oder far calls, die über das komplette erste Megabyte
reichen.
Der Prozessor und DOS verfügt dabei über keine Rechte und keinen
Speicherschutz. Du kannst Code z.B. direkt im Bildschirmspeichersegment
ausführen, das sorgt für die erste Überraschung wenn jemand Dein
Programm tracen möchte.
Programmierer schrieb:> Lern ARM-Assembler
Welchen genau? Es gibt mehr als einen. Bei x86 allerdings auch...
Fakt ist: wer einen wirklich gelernt und praktisch angewendet hat, kann
sich auch in jeden anderen recht schnell reinfinden. Ja, gelegentlich
muss man neue Konzepte lernen, wenn man die Architekturen wechselt (und
natürlich immer einen neuen Befehlssatz). Aber das ist trivial. Reine
Lernarbeit.
Das Gelernte optimal anwenden ist dann eine ganz andere Nummer. Da
können Jahre vergehen...
Nachtrag weil zu spät für Edith:
Oder Du machst Dir das einfacher und gehst gleich zu Win32 und protected
mode über. Dann kannst Du alle Segmentregister vergessen und alle
32-Bit-Register (EIP, ESI, EDI, ESP, EAX etc.) reichen über den
kompletten adressierbaren 4GB-Speicherblock. Die Segmentregister werden
dabei automatisch so initialisiert, daß alle Datenblöcke (Code, Daten,
Stack) bei 0h beginnen. Du kannst dann aber z.B. ESI/EDI megabyteweise
so weit hochzählen wie Du brauchst (bzw. bis Du das zugewiesene
Datensegment verlässt, ein Byte weiter gibts einen Ausnahmefehler) ohne
Dich um die Segmentierung zu kümmern.
c-hater schrieb:> Welchen genau? Es gibt mehr als einen. Bei x86 allerdings auch...
Am besten den GNU-Assembler. Der ist am Weitesten verbreitet, passend
für (Embedded) Linux und Android und natürlich GCC, und Open Source.
Die Unterschiede bestehen sowieso nur in den Direktiven; die
Instruktionen selbst sind fix.
Ben B. schrieb:> Wenn es nur um eine Adresse geht ist das Segmentregister Adresse/10h. In> das normale Register kommen die letzten vier Bits der Adresse
Bei ARM: Die 32bits der Adresse kommen in ein 32bit Register. Fertig.
Und es gibt 13 General Purpose Register, nicht nur 4...
> Ich möchte bitte den X86 ASM kennenlernen.> Bei ARM: Die 32bits der Adresse kommen in ein 32bit Register. Fertig.
Super Einwurf. Sechs, setzen!
@TE: Edith wollte noch sagen, Du kannst auch gleich zu Win64
durchmarschieren, dann sind es nicht mehr EAX, ESI, EDI, EIP etc.
sondern RAX, RSI, RDI und natürlich RIP. Außerdem sind dabei die
Befehlssatzerweiterungen wie SSE, AVX usw. nutzbar.
wenn du einen guten Debugger auf unterster Ebene suchst, nimm den AFD
pro... den gab es schon vor dieser Partei :-) da kannst du selbst kleine
Programme direkt schreiben
peter schrieb:> Hallo danke Einer.>> Funktioniert toll.>> Ich habe in den 3 x86-asm-PDF die ich geangelt habe nicht gefunden.
Und wieder hat einer einem grezdilen C&Pler dabei geholfen, weiter dumm
bleiben zu können.
Ich hoffe "Einer" wusste, was er tat und übernimmt die volle
Verantwortung für seine Tat...
Sorry, x86 war und ist Müll.
Leider hat das ausgefeilte Marketing dafür gesorgt, dass wir uns heute
noch diesen Müll antun.
NS32k oder M68k waren damals ihrer Zeit voraus. MIPS und ARM sowieso.
Leider ist jeder Mickysoft hinterher gerannt und somit x86.
Es gab und es gibt besseres...
OldMan schrieb:> NS32k oder M68k waren damals ihrer Zeit voraus
Und natürlich war Video2000 das beste Videoformat, und Borgward hatte
die besten Autos - das Leben ist halt hart aber ungerecht.
Wieso lebst du eigentlich noch?
Georg
Ja, damals waren NS32000 und der 68000 er technologisch besser. Aber die
Lieferanten und Hersteller wahrscheinlich etwas zickiger. Man brauchte
damals, heute ueberigens auch noch, kein ausgefeiltes Marketing wenn die
anderen zickig tun.
Bedeutet .. wie ist der Support, gibt es ein Dev-Kit, was kostet der
ASM, was kostet der Compiler, usw.
Ich habe mir auch einen x86 zusammengebaut, weil ich vom 8085 her kam.
Den PC gab's damals noch nicht.
Ich habe mir also die Chips bestellt. Damals gab es noch support
ingenieure, die das konnten. Ich konnte mich also eine halbe Stunde per
Telephon mit so einem Supprt Ingenieur fuer die Intel Familie ueber ein
Registerfeature des 8059 Interrupt Controller unterhalten. Ebenso ueber
den DRAM Controller, wenn etwas nicht lief wie ich mir das vorstellte.
Als dann diese ausgenutzt wurden, also Support beanspruchen und dann
ueber einen Broker bestellen, wurden sie durch Sachbearbeiterinnen
ersetzt, welche nur noch die Artikelnummer und die anzahl wissen
wollten.
Das 2.5cm dicke iAPX86 Manual wurde gratis geschickt. So machte man eben
damals das Geschaeft. Ich blieb diesen Produkten treu.
Anders zB auch gute Controller, die Analog Devices Blackfin DSP. Der
Compiler beginnt ab 5000 Euro. Ist ein No-go zum Reinschauen fuer
Absolventen.
Oder TI - TMS320 - ich hab den Namen vergessen, die IDE total schlecht
und ueberteuert, auch wenn die chips eigentlich gut waren.
OldMan schrieb:> NS32k oder M68k waren damals ihrer Zeit voraus.
Nö, denn danach kamen die RISC, keine Komplexitätsmonster. Besonders
wenn man NS32K betrachtet, und dessen Steigerung, NECs V60/70. Diese
Dinger standen nämlich voll in der VAX Tradition, den Prozessor intern
so kompliziert zu machen, dass man ihn ohne Blick in die Fehlerliste
nicht verwenden konnte, und eine Beschleunigung kaum möglich ist.
Es war kein Zufall, dass Motorola irgendwann den Versuch aufgab, die
hochkomplexe 68020 Architektur zu beschleunigen und auf 88000 setzte.
Wie auch DEC ebendeshalb die VAX Architektur aufgab und übergangsweise
erst MIPS, dann Alpha verwendete.
Oha, komplexes Thema.
Im Grunde hängt das von Deinem Programm und der Art der Unterfunkion ab.
Interrupt-Funktionen (z.B. von TSR-Programmen) müssen grundsätzliche
alle Register und das Flag-Register sichern, da unbestimmt ist wann sie
aufgerufen werden. Wenn man da einen Fehler macht, hat man quasi sofort
einen Crash. Es muß quasi alles so hinterlassen werden, wie man es beim
Einsprung vorgefunden hat.
Also z.B. für 16 Bit Interrupt-Routine:
begin: PUSHA
PUSH DS (falls man die Segmentregister braucht)
PUSH ES
MOV AX,CS
MOV DS,AX
MOV ES,AX
[..] (Programm)
POP ES
POP DS
POPA
IRET
Und ein bißchen Vorsicht mit der Verwendung des Stacks, die
Interruptroutine verwendet den Stack des Programms, welches gerade
unterbrochen wurde und darf diesen nicht überfüllen. Das gibt sonst
einen sogenannten stack overflow, dabei werden meistens die Daten und in
extremen Fällen der Code des unterbrochenen Programms zerstört.
---
Bei Deinen eigenen Unterfunktionen musst Du nur das sichern, was für
Dich wichtig ist. Wenn Deinem Programm nach dem Aufruf einer Funktion
egal ist, wie die Register aussehen (etwa weil Du sie sowieso gleich
alle neu lädst) brauchst Du auch nichts sichern. Das böse Erwachen kommt
dann, wenn Du diese Funktion irgendwann an einer Stelle aufrufst, wo das
nicht egal ist. Außerdem brauchst Du die Flags normalerweise nicht zu
sichern, da Du normalerweise keine Funktion zwischen einem Vergleich und
den nachfolgenden bedingten Sprüngen ausführen wirst (was bei einer
Interruptfunktion jederzeit passieren kann).
AX wird bei sowas meistens nie gesichert, da dort oft Rückgabewerte
abgelegt werden. Dagegen wird der Zähler CX sehr oft gesichert.
begin: PUSH BX
PUSH CX
[..] (Programm im eigenen 64K Codesegment)
ok: MOV AX,0
JMP SHORT exit
fail: MOV AX,1
exit: POP CX
POP BX
RET
Bei sehr vielen gesicherten Registern kann man auch PUSHA/POPA
verwenden, muß Rückgabewerte dann aber direkt auf dem Stack verändern
damit diese durch das POPA nicht überschrieben werden.
Ich habe in meinen frühen Jahren viel Assembler geschrieben: Z80, 68000,
Vax und ein paar Exoten.
Aber der krankeste Assembler war 8086. Durch diese Segmentregister hatte
man Probleme, die es auf anderen Architekturen nicht gab. Das machte
keinen Spass und führte nur zu Hirnverrenkungen. Erst mit den 32Bittern
wurde es etwas besser.
Meine Empfehlung: lerne ruhig mal einen Assembler, das ist eine gute
Erfahrung.
Aber: nimm etwas anderes als 8086, nimm etwas anderes als 8086 und nimm
etwas anderes als 8086.
Wähle eine Architektur, die man evtl auch noch mal praktisch anwenden
könnte. Ich fände jetzt die Risc-V Architektur interessant.
Ben B. schrieb:> Interrupt-Funktionen (z.B. von TSR-Programmen) müssen grundsätzliche> alle Register und das Flag-Register sichern
Das ist natürlich nicht richtig. Gesichert werden muss nur, was in der
Interrupt Service Routine verändert wird, und das ist wesentlich
weniger. Es ist unsinnig Daten mit Push und Pop zu speichern, die nach
dem Ende der ISR sowieso gleich sind. Das machen nur ganz dumme
Programme oder Programmierer.
Georg
PittyJ schrieb:> Aber der krankeste Assembler war 8086. Durch diese Segmentregister hatte> man Probleme, die es auf anderen Architekturen nicht gab. Das machte> keinen Spass und führte nur zu Hirnverrenkungen. Erst mit den 32Bittern> wurde es etwas besser.
Ich verstehe echt nicht warum dauernd auf den Segmentregistern
rumgeritten
wird.
Die setzt du normalerweise einmal, und das wars.
Ich habe 8086 Assembler immer gemocht, klare Syntax und effiziente
Architektur. Wenn die so schlecht wäre, dann gäbe es sie heute nicht
mehr.
udok schrieb:> Die setzt du normalerweise einmal, und das wars.
Nur wenn das Programm klein genug war.
> Wenn die so schlecht wäre, dann gäbe es sie heute nicht mehr.
Es war nicht die Qualität der Architektur, die 8086 am Leben hielt,
sondern IBM und deren PC. Und es war auch nicht der Qualität der ISA,
die hinter IBMs Entscheidung stand. Sondern der Mangel an Alternativen,
bei denen IBM zum Zeitpunkt der Entscheidung davon ausgehen konnte, dass
sie zum Zeitpunkt der Markteinführung stabil und gut verfügbar wären.
Das war bei der 68000 nicht der Fall.
Die Problematik von Daten jenseits von 64kB dürfte damals nicht akut
erschienen sein. Als Entscheidung fürs Jahrhundert war das ja nicht
gedacht. Auch Intel hatte 8086 nur als kurzen Zwischenschritt zu 432
gesehen.
Späteren waren dann die schiere Masse und die daraus folgende geforderte
Kompatibilität das wichtigste Kriterium.
Ich verstehe eure Probleme nicht. Die wenigsten Assembler-Programme
damals waren größer als 64kB Code. Meine DOS-Viren z.B. waren um die
70kB Quelltext, aber "nur" 6..7kB Code oder so, einschließlich
initialisierter Daten. Die Dinger hatten keine Schadfunktion, aber dafür
COM/EXE Stealth mit polymorpher Verschlüsselung. Die konnten viel um
sich zu verstecken, das alles zu erklären würde hier den Rahmen sprengen
- und das mit nur 6..7kB Code. Und nein, ich hab sie nicht auf die
Menschheit losgelassen oder in der Schule getestet etc. bevor
irgendjemand fragt. Aber das waren so ziemlich die größten
Assembler-Programme, die ich geschrieben habe und selbst die waren weit
von der "kritischen" 64kB Code Marke entfernt.
Selbst wenn man nur einmal zwischen Hauptprogramm und Funktionen
aufteilt, erhält man schon 128kB maximale Code-Größe. Man könnte CS auch
für jede Funktion neu setzen. Gefühlt hat das jede Hochsprache gemacht,
wenn man sich sowas im Disassembler angeschaut hat, war da alles voll
mit far calls.
Es nervt noch nicht mal bei großen Datenmengen, da man sich Offsets
größer 65535 sowieso in zwei 16-Bit-Worten merken muß. Das obere Wort
multipliziert man mit 1000h und addiert die Anfangsadresse des
Datenblocks, fertig ist der Wert für's Datensegment. Unter DOS gibts
sowieso nur 640kB Speicher, das ist weit weniger als auf eine Diskette
passt. Für Assembler-Programme ist das echt viel, für Daten manchmal
viel zu wenig. Da fangen dann die Spielereien mit HIMEM oder
DOS-Extendern (DOS4GW z.B.) an.
Naja ist sowieso lange vorbei, die Geschichte. Heute braucht man das
nicht mehr, läuft sowieso alles im protected mode. Ein einzelnes
Codesegment wird für sein DOS-Lernvorhaben ausreichend sein.
A. K. schrieb:> udok schrieb:>> Die setzt du normalerweise einmal, und das wars.>> Nur wenn das Programm klein genug war.>>> Wenn die so schlecht wäre, dann gäbe es sie heute nicht mehr.>> Es war nicht die Qualität der Architektur, die 8086 am Leben hielt,> sondern IBM und deren PC. Und es war auch nicht der Qualität der ISA,> die hinter IBMs Entscheidung stand. Sondern der Mangel an Alternativen,> bei denen IBM zum Zeitpunkt der Entscheidung davon ausgehen konnte, dass> sie zum Zeitpunkt der Markteinführung stabil und gut verfügbar wären.> Das war bei der 68000 nicht der Fall.
Doch es war die Qualität der x86 Architektur.
Die Ingenieure damals wussten noch was sie taten, und wo genau das
Gatter Nr. 758 am Die zu finden war.
Keine andere Architektur ist so Speichereffizient, und dabei auch
schnell.
Und Speicher war damals richtig teuer!
Mal eben 10 MByte nebenbei in C++ für irgendwas allozieren,
ohne das der Programmierer es überhaupt merkt, ging damals nicht.
Dabei ist x86 sehr einfach zu programmieren,
auch in Assembler wenn es sein musste.
68k und die Konkurrenz war zu langsam am Markt, und auch teurer.
Interessanterweise gilt das auch heute noch.
Selbt in Supercomputern, wo Geld keine grosse Rolle spielt,
läuft fast nur x64.
Da kannst du deinen Asm Code von damals unverändert laufen lassen.
udok schrieb:> Selbt in Supercomputern, wo Geld keine grosse Rolle spielt,> läuft fast nur x64.
Da läuft fast nur x64, weil diese Prozessoren dank Masseneinsatz in PCs
sowohl leistungsfähig als auch günstig sind. Zudem werden die
mittlerweile oft von GPUs begleitet, die die eigentliche Aufgabe
bearbeiten und genauso von dem Masseneinsatz in PCs profitieren.
Mit der Qualität der 8086 ISA hat das wenig zu tun. Segmentregister
spielen in x64 ohnehin nur eine Nischenrolle.
> Da kannst du deinen Asm Code von damals unverändert laufen lassen.
Auf den GPUs? ;-)
Aber wenn die x86/x64 Architektur (ISA) schlecht wäre, dann müsste es
irgendeinen CPU Hersteller geben, der sagt:
Meine CPU ist 2x so schnell wie x86/x64!
Sagt aber komischerweise keiner, daher ist die x64 ISA wohl doch sehr
gut.
udok schrieb:> Meine CPU ist 2x so schnell wie x86/x64!
IBM hat solche (Power), und ARM Prozessoren sind Energie effizienter.
Intel hat es mit Itanium sogar selbst versucht, weil sie selbst x86 los
werden wollten.
Mangels Massenmarkt und entsprechenden niedrigen Preisen sind sie aber
nicht (sofort) konkurrenzfähig und können es daher in der Liga der PC's
nicht mit x86 aufnehmen.
Hier dominiert der Markt und Massenproduktion die Auswahl, nicht die
Qualität. Siehe VHS...
udok schrieb:> Sagt aber komischerweise keiner, daher ist die x64 ISA wohl doch sehr> gut.
Mit etwas Glück kann Torben dir mittlerweile den Unterschied zwischen
Befehlssatz und Implementierung nahe bringen. ;-)
udok schrieb:> Meine CPU ist 2x so schnell wie x86/x64!
Hier:
https://www.forbes.com/sites/tiriasresearch/2018/08/09/ibm-power-9-offers-a-complete-alternative-to-intel-xeon/#65e9b04c23d4
"The [IBM] Power9 competes directly with Intel’s highest performance
Xeon Scalable Processors (SP) but offers up to twice the performance per
core and just shy of twice the memory bandwidth performance, making it
the perfect choice for performance-hungry, scale-up applications."
Das kann natürlich im PC-Markt nicht konkurrieren. Aber die Behauptung,
x86(_64) wäre unübertreffbar, ist absurd. Intel war zu Beginn führend in
Halbleiter-Fertigung, kannte sich aber nicht mit Prozessoren aus, wollte
aber auch mal eine Architektur zusammenbasteln, welche aber von Anfang
an bestehenden Systemen unterlegen war. Zusammen mit den DOS-Systemen,
welche kein Vergleich zu den etablierten Unix-Systemen waren, wurde eine
Plattform ins Leben gerufen, welche lediglich über Preis und Massenmarkt
überlebt und letztlich die anderen verdrängt hat. Der durch die Fehler
von Intel und Microsoft verursachte Schaden (z.B. durch mangelnde
Sicherheit und Programmier-Aufwand) dürfte kaum zu beziffern sein. Erst
in den letzten Jahren wurden die Probleme mehr oder weniger gut
geflickt.
Im Serverbereich hält sich x86(_64) und auch Windows Server nur, weil
die Programmierer (und die Entscheidungs-Treffer) das von zuhause kennen
und ihre Kenntnisse dort leicht übertragen können; nicht, weil es
tatsächlich so toll wäre.
Für mich klingt das nach den üblichen Verschwörungstheorien
spätpupertierender 20 Jähriger.
Geizhals liefert mir zu Power9 nur Lüfter:
https://geizhals.at/?fs=power9&hloc=at&hloc=de&in=
Irgendwelche Ideen, wo ich den kaufen kann?
Programmierer schrieb:> Das kann natürlich im PC-Markt nicht konkurrieren. Aber die Behauptung,> x86(_64) wäre unübertreffbar, ist absurd. Intel war zu Beginn führend in> Halbleiter-Fertigung, kannte sich aber nicht mit Prozessoren aus, wollte
Keiner hat gesagt, das x64 unübertreffbar ist.
Leseschwäche?
Hier wird dir geholfen:
https://www.lernfoerderung.de/lesen/leseschwaeche/
udok schrieb:> Für mich klingt das nach den üblichen Verschwörungstheorien> spätpupertierender 20 Jähriger.
Beweihräucherung von Intel klingt nach Gamer-Fanboytum ("ich hab einen
Intel i7 in meinem blinkenden Gaming-PC, das ist der tollste Prozessor
wo gibt").
> Geizhals liefert mir zu Power9 nur Lüfter:
Und? Rechenzentren-Betreiber shoppen wohl kaum über GH.
udok schrieb:> Leseschwäche?>> Hier wird dir geholfen:
Vielen Dank, ich hatte dich falsch verstanden. Das
udok schrieb:> Meine CPU ist 2x so schnell wie x86/x64!>> Sagt aber komischerweise keiner, daher ist die x64 ISA wohl doch sehr> gut.
klang so, als würdest du nahe legen, dass es keine schnelleren CPUs
gibt, aber es war natürlich nur die Existenz von doppelt so schnellen
CPUs ausgeschlossen, aber nicht die Existenz von z.B. 3x so schnellen
CPUs. Witzigerweise ist das genau falsch, denn es gibt ja eben genau
doppelt so schnelle CPUs. Naja, Lügen verbreiten ist besser als
Leseschwäche haben, oder?
peter schrieb:> Die Adresse $b8000 ist ja zu gross (CGA-Adresse) für meine Denkweise.
Man muss(te) zusehen, wie man mit 16 Bit einen 20 Bit breiten Adressbus
bedient.
Programmierer schrieb:> klang so, als würdest du nahe legen, dass es keine schnelleren CPUs> gibt, aber es war natürlich nur die Existenz von doppelt so schnellen> CPUs ausgeschlossen, aber nicht die Existenz von z.B. 3x so schnellen> CPUs. Witzigerweise ist das genau falsch, denn es gibt ja eben genau> doppelt so schnelle CPUs. Naja, Lügen verbreiten ist besser als> Leseschwäche haben, oder?
Ja lass mal gut sein. Is mir schon klar, dass du recht hast, und der
beste bist...
PittyJ schrieb:> Aber der krankeste Assembler war 8086.
Wenn du das wirklich glaubst, kannst du wirklich nicht viele
Architekturen kennengelernt haben...
Segmentregister, lächerliches Problem...