Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Image deflaten

1 view
Skip to first unread message

Jens Kallup

unread,
Jun 17, 2020, 8:59:51 AM6/17/20
to
Hallo Gemeinde,

ich habe hier einen Quellcode, den ich aus den Internet habe.
Ich habe diesen nach "nasm" konvertiert, so dass dieser auch
mit nasm übersetzt werden kann.

Die Sache ist nur die:
Wie wende ich diesen Code an?
Sprich, was muss ich machen, damit ein Image via 286/386 Code
seinen Dienst leistet.

Folgendes dazu:
- habe ein raw Image, das im MBR Sektoren ließt, und dann
verschiedene Sachen macht - eigentlich nur spielereien.
Am Bootsektor hängt noch dieser Code.
Danach folgt ein mit "lz4" (lzma4) (unter Linux erstelltes/komprimiertes
Image.
Habe kein MemoryPaging, und versuche, falls möglich, den Speicher
< 1MB zu nutzen.
Sprich es müsste ein "statischer" Speicher, der Groß genug ist für das
entpackte Image angelegt werden.
Doch wie macht man das, wenn keine "malloc" Funktion zur Verfügung
steht - nur ein reines BootImage?

Mit freundlichen Grüßen

Jens

; Decompresses Y. Collet's LZ4 compressed stream data in 16-bit real mode.
; Optimized for 8088/8086 CPUs.
;
; Code by Trixter/Hornet (tri...@oldskool.org) on 2013-01-05
; Updated 2019-06-17 -- thanks to Peter Ferrie, Terje Mathsen,
; and Axel Kern for suggestions and improvements!
;
; Updated 2019-06-30: Fixed an alignment bug in lz4_decompress_small
; Updated 2020-03-14: Speed updates: Pavel Zagrebin

[bits 16]

;---------------------------------------------------------------
; function lz4_decompress(inb,outb:pointer):word;
;
; Decompresses an LZ4 stream file with a compressed chunk 64K or less in
size.
; Input:
; DS:SI Location of source data. DWORD magic header and DWORD chunk size
; must be intact; it is best to load the entire LZ4 file into this
; location before calling this code.
;
; Output:
; ES:DI Decompressed data. If using an entire 64K segment, decompression
; is "safe" because overruns will wrap around the segment.
; AX Size of decompressed data.
;
; Trashes AX, BX, CX, DX, SI, DI
; ...so preserve what you need before calling this code.
;---------------------------------------------------------------
;Pavel Zagrebin is credited with the following speedups:
; Changing the end-of-file comparison to self-modifying offset
; push ds;pop ds->mov ds,bp
; adc cx,cx;rep movsb->jnc
; NOTE: I can't explain it, but with no extraneous background interrupts,
; timings are taking longer than normal on my IBM 5160. So, we have to
; reset our timing numbers here:
; Old timings: shuttle 85038 text 45720 robotron 307796 ---
; After Pavel's speedups:
; New timings: shuttle 81982 text 43664 robotron 296081 +++
;
---------------------------------------------------------------------------

section .text
global lz4_decompress
lz4_decompress:
push ds ;preserve compiler assumptions
les di,[lzmaBuffer_dst] ;load target buffer
push di ;save original starting offset (in case
!= 0)
lds si,[lzmaBuffer_src] ;load source buffer
add si,4 ;skip magic number
cld ;make strings copy forward

; mov bx, SHR4table ;prepare BX for XLAT later on
; lodsw ;load chunk size low 16-bit word
; mov bp,ax ;BP = size of compressed chunk
; lodsw ;load chunk size high 16-bit word

add bp,si ;BP = threshold to stop decompression
or ax,ax ;is high word non-zero?
jnz done ;If so, chunk too big or malformed, abort

starttoken:
lodsb ;grab token to AL
mov dx,ax ;preserve packed token in DX
; cs xlat ;unpack upper 4 bits, faster than SHR reg,cl
mov cl, 4
shr al, cl
mov cx,ax ;CX = unpacked literal length token
jcxz copymatches ;if CX = 0, no literals; try matches
cmp al,0Fh ;is it 15?
jne doliteralcopy1 ;if so, build full length, else start
copying
build1stcount: ;this first count build is not the same
lodsb ;fall-through jump as the one in the
main loop
add cx,ax ;because it is more likely that the
very first
cmp al,0FFh ;length is 15 or more
je build1stcount
doliteralcopy1:
rep movsb ;src and dst might overlap so do this
by bytes

;At this point, we might be done; all LZ4 data ends with five literals
and the
;offset token is ignored. If we're at the end of our compressed chunk,
stop.

cmp si,bp ;are we at the end of our compressed chunk?
mov word [cs:end_of_chunk+2],bp
;self-modifying cmp si,xxxx
mov bp,ds ;now we can use bp for restoring ds
jae done ;if so, jump to exit; otherwise, process
match

copymatches:
lodsw ;AX = match offset
xchg dx,ax ;AX = packed token, DX = match offset
and al,0Fh ;unpack match length token
cmp al,0Fh ;is it 15?
xchg cx,ax ;(doesn't affect flags); don't need ax
any more
je buildmcount ;if not, start copying, otherwise build
count

domatchcopy:
cmp dx,2 ;if match offset=1 or 2, we're
repeating a value
jbe domatchfill ;if so, perform RLE expansion optimally
xchg si,ax ;ds:si saved
mov si,di
sub si,dx
mov dx,es
mov ds,dx ;ds:si points at match; es:di points at
dest
movsw ;minimum match is 4 bytes; move them
ourselves
shr cx,1
jnc even
movsb
even:
movsw
rep movsw ;cx contains count-4 so copy the rest
xchg si,ax
mov ds,bp

parsetoken: ;CX always 0 here because of REP
xchg cx,ax ;zero ah here to benefit other reg loads
lodsb ;grab token to AL
mov dx,ax ;preserve packed token in DX
copyliterals: ;next 5 lines are 8088-optimal, do not
rearrange
; cs xlat ;unpack upper 4 bits, faster than SHR reg,cl
mov cl, 4
shr al, cl

mov cx,ax ;CX = unpacked literal length token
jcxz copymatches ;if CX = 0, no literals; try matches
cmp al,0Fh ;is it 15?
je buildlcount ;if so, build full length, else start
copying
doliteralcopy: ;src and dst might overlap so do this by bytes
rep movsb ;if cx=0 nothing happens

;At this point, we might be done; all LZ4 data ends with five literals
and the
;offset token is ignored. If we're at the end of our compressed chunk,
stop.

testformore:
end_of_chunk:
cmp si,256 ;this constant is patched with the end address
jb copymatches ;if not, keep going
jmp done ;if so, end

domatchfill:
je domatchfill2 ;if DX=2, RLE by word, else by byte
domatchfill1:
mov al,[es:di-1] ;load byte we are filling with
mov ah,al ;copy to ah so we can do 16-bit fills
stosw ;minimum match is 4 bytes, so we fill four
stosw
inc cx ;round up for the shift
shr cx,1 ;CX = remaining (count+1)/2
rep stosw ;includes odd byte - ok because LZ4
never ends with matches
adc di,-1 ;Adjust dest unless original count was even
jmp parsetoken ;continue decompressing

domatchfill2:
mov ax,[es:di-2] ;load word we are filling with
stosw ;minimum match is 4 bytes, so we fill four
stosw
inc cx ;round up for the shift
shr cx,1 ;CX = remaining (count+1)/2
rep stosw ;includes odd byte - ok because LZ4
never ends with matches
adc di,-1 ;Adjust dest unless original count was even
jmp parsetoken ;continue decompressing

buildlcount: ;build full literal length count
lodsb ;get next literal count byte
add cx,ax ;increase count
cmp al,0FFh ;more count bytes to read?
je buildlcount
jmp doliteralcopy

buildmcount: ;build full match length count - AX is 0
lodsb ;get next literal count byte
add cx,ax ;increase count
cmp al,0FFh ;more count bytes to read?
je buildmcount
jmp domatchcopy

done:
pop ax ;retrieve previous starting offset
sub di,ax ;subtract prev offset from where we are now
xchg ax,di ;AX = decompressed size
pop ds ;restore compiler assumptions
ret

section .data
lzmaBuffer_src: dw 0 ; decode: source of buffer pointer
lzmaBuffer_dst: dw 0 ; decode: destination

section .text
end_of_lz4:

Stefan Reuther

unread,
Jun 17, 2020, 12:28:24 PM6/17/20
to
Am 17.06.2020 um 14:59 schrieb Jens Kallup:
> Sprich es müsste ein "statischer" Speicher, der Groß genug ist für das
> entpackte Image angelegt werden.
> Doch wie macht man das, wenn keine "malloc" Funktion zur Verfügung
> steht - nur ein reines BootImage?

Wenn man ein Bootloader ist, gehört einem der gesamte Speicher.

Also sucht man sich einfach einen schönen Bereich raus, der nicht schon
fest vom System vergeben ist, und benutzt den.

https://wiki.osdev.org/Memory_Map_(x86)


Stefan

Jens Kallup

unread,
Jun 17, 2020, 12:46:20 PM6/17/20
to
Am 17.06.20 um 18:18 schrieb Stefan Reuther:
> Also sucht man sich einfach einen schönen Bereich raus, der nicht schon
> fest vom System vergeben ist, und benutzt den.

Hallo Stefan,

schön von Dir zu hören.
Mal angenommen, das segment 0x1000 mit offset 0x0000, also 1000:0000
oder linear 0x10000000
dürfte an die Grenze von 1 MB kommen?
jetzt müsste man aber erstmal die Daten in den Speicher legen.
Ok, das macht man mit read sectors vom int 0x13.
Das gibt dann den Bereich wieder zurück wo der Puffer liegt.

Ich veröffentliche mal den Code, so dass Du sehen kannst, was ich
überhaupt hier treibe.

Ich habe vor, die Daten, die hinter dem MBR + deflater code, das Image,
dass hinter diesen Daten liegt zu entpacken, den ich vorerst mit
lz4 unter Linux gepackt habe.

Ob das erstmal einen Sinn macht, sei dahin gestellt.
Erst mal sehen, ob das überhaupt klappt.

ich habe ein Script dazu gepackt, das den ganzen Krimmel zusamen preßt.
im ./build.sh und im ./start.sh.

Als VM verwende ich hier QEMU i386.

Ok, nun hier zum Code auf meinen GIT:

https://github.com/paule32/selfmade_os

Gruß Jens

Bernhard Schornak

unread,
Jun 18, 2020, 9:18:54 AM6/18/20
to
Jens Kallup schrieb:


> Am 17.06.20 um 18:18 schrieb Stefan Reuther:
>> Also sucht man sich einfach einen schönen Bereich raus, der nicht schon
>> fest vom System vergeben ist, und benutzt den.
>
> Hallo Stefan,
>
> schön von Dir zu hören.
> Mal angenommen, das segment 0x1000 mit offset 0x0000, also 1000:0000
> oder linear 0x10000000


1000:0000 = 00010000 (1000 >> 12 + 0000)

Segmentregister (CS, DS, ES, SS) enthalten immer das 5. Digit der
Adresse, also 0000.0000 ... 000F.FFFF = 64 kiB * 16 = 1 MiB.


> dürfte an die Grenze von 1 MB kommen?


Nein.


> jetzt müsste man aber erstmal die Daten in den Speicher legen.
> Ok, das macht man mit read sectors vom int 0x13.
> Das gibt dann den Bereich wieder zurück wo der Puffer liegt.


Braucht man die Adresse beim Lesen und Schreiben inzwischen nicht
mehr in ES:BX an den Interrupt übergeben? Ergibt keinen Sinn, das
extra abzufragen...


Grüße aus Augsburg

Bernhard Schornak

Stefan Reuther

unread,
Jun 18, 2020, 12:03:26 PM6/18/20
to
Hallo,

Am 17.06.2020 um 18:46 schrieb Jens Kallup:
> Am 17.06.20 um 18:18 schrieb Stefan Reuther:
>> Also sucht man sich einfach einen schönen Bereich raus, der nicht schon
>> fest vom System vergeben ist, und benutzt den.
>
> schön von Dir zu hören.
> Mal angenommen, das segment 0x1000 mit offset 0x0000, also 1000:0000
> oder linear 0x10000000
> dürfte an die Grenze von 1 MB kommen?

Nein, hat Bernhard ja schon erklärt.

Ich hatte die Memory Map verlinkt. Zusammengefasst:

00000 - 004FF = IVT + BIOS Daten
00500 - 07BFF = frei
07C00 - 07DFF = hier wurde dein Bootsektor hingeladen
07E00 - ????F = frei
????0 - 9FFFF = EBDA
A0000 - BFFFF = Bildspeicher

Segmentadresse der EBDA steht an 0040E (also 0040:000E oder 0000:040E,
was immer dir besser gefällt). Damit ist hinter deinem Bootsektor (also
07E0:0000 oder 0000:7E00 oder wie auch immer) bis zur EBDA alles frei,
um die 600k.

> jetzt müsste man aber erstmal die Daten in den Speicher legen.
> Ok, das macht man mit read sectors vom int 0x13.
> Das gibt dann den Bereich wieder zurück wo der Puffer liegt.

Die Pufferadresse musst du angeben (ES:BX).

http://www.ctyme.com/intr/rb-0607.htm

Wenn du mehr als die genannten 600k brauchst, brauchst du Protected
Mode, dann kannst du aber den INT 13 nicht mehr verwenden.

Du kannst auch deinen eigenen Code erstmal verschieben, z.B. an 00500,
um noch ein paar k mehr zu bekommen.


Stefan

Jens Kallup

unread,
Jun 18, 2020, 1:26:13 PM6/18/20
to
Hallo Gemeinde,

Danke für das große entgegen kommen!

Ohne das jetzt alles getestet zu haben:
der Quellcode stimmt soweit?

Weil, das ist "fast" nicht die originale Fassung.
Ich habe den Quellcode aus dem Internet, und im
Original wurde noch eine Look-Up Tabelle
verwendet.

Im ##asm channel habe ich auch schon viele andere
Informationen bekommen, die den Befehlt XLAT
betreffen, und scheinbar diese Tabelle überflüssig
machen.

Aber würde gerne nochmal Eure Meinung dazu
einholen.

Gruß, Jens

Bernhard Schornak

unread,
Jun 18, 2020, 2:01:01 PM6/18/20
to
Jens Kallup schrieb:


> Ich habe den Quellcode aus dem Internet, und im
> Original wurde noch eine Look-Up Tabelle verwendet.


Ist eine gute Idee, Tabellen beizubehalten.


> Im ##asm channel habe ich auch schon viele andere
> Informationen bekommen, die den Befehlt XLAT
> betreffen, und scheinbar diese Tabelle überflüssig
> machen.


Nicht wirklich. XLAT ist *sehr* langsam und Du kannst damit
nur 8-Bit-Werte einer 256 Byte grossen Tabelle nach AL ein-
lesen. Indirekt indizierte Zugriffe wie

mov %rAX, 0x00(%rBX, %rCX, n) mit n = 1, 2, 4 oder 8

zum Schreiben oder

mov 0x00(%rBX, %rCX, n), %rAX

zum Lesen beliebiger Registerbreiten sind flexibler und mit
4 Taktzyklen (5 bei Byte und Worten) auch schneller als der
in Mikrocode umgesetzte XLAT-Befehl.

Peter J. Holzer

unread,
Jun 23, 2020, 5:31:50 AM6/23/20
to
On 2020-06-18 13:17, Bernhard Schornak <scho...@web.de> wrote:
> Jens Kallup schrieb:
>> Am 17.06.20 um 18:18 schrieb Stefan Reuther:
>> Mal angenommen, das segment 0x1000 mit offset 0x0000, also 1000:0000
>> oder linear 0x10000000
>
> 1000:0000 = 00010000 (1000 >> 12 + 0000)
>
> Segmentregister (CS, DS, ES, SS) enthalten immer das 5. Digit der
> Adresse, also 0000.0000 ... 000F.FFFF = 64 kiB * 16 = 1 MiB.

Nein, das Segment-Register wird um 4 Positionen nach links geshiftet und
dann addiert. Hier macht das keinen Unterschied, weil die unteren 12
Bits 0 sind:

1000:0000 = 10000 + 0000 = 10000

aber das muss nicht so sein:

1234:5678 = 12340 + 5678 = 179B8 (nicht 15678!)

und

FFFF:FFFF = FFFF0 + FFFF = 10FFEF

(da ist man dann tatsächlich jenseits von 1MB, was bei 286 und später
auch funktioniert (für die Kompatibilität zum 8086 sorgt(e) das
berüchtigte A20-Gate))

hp

Bernhard Schornak

unread,
Jun 23, 2020, 4:06:34 PM6/23/20
to
Peter J. Holzer schrieb:


> On 2020-06-18 13:17, Bernhard Schornak <scho...@web.de> wrote:
>> Jens Kallup schrieb:
>>> Am 17.06.20 um 18:18 schrieb Stefan Reuther:
>>> Mal angenommen, das segment 0x1000 mit offset 0x0000, also 1000:0000
>>> oder linear 0x10000000
>>
>> 1000:0000 = 00010000 (1000 >> 12 + 0000)
>>
>> Segmentregister (CS, DS, ES, SS) enthalten immer das 5. Digit der
>> Adresse, also 0000.0000 ... 000F.FFFF = 64 kiB * 16 = 1 MiB.
>
> Nein, das Segment-Register wird um 4 Positionen nach links geshiftet und
> dann addiert. Hier macht das keinen Unterschied, weil die unteren 12
> Bits 0 sind:
>
> 1000:0000 = 10000 + 0000 = 10000


CS, DS, ES und SS sind (auch in modernen Prozessoren!) 16 Bit breite
Register - wenn man 0x1000 in einem 16-Bit breiten Register vier Bit
nach links schiebt, bleibt Null übrig, und das Überlaufbit wird u.U.
gesetzt. Dein Weg wäre damit keine Option für x86-Prozessoren.


> aber das muss nicht so sein:
>
> 1234:5678 = 12340 + 5678 = 179B8 (nicht 15678!)


Die Segmentregister selektieren jeweils einen der 65536 Paragraphen,
das sind 16-Byte große "Scheibchen" des Speichers. Das vermeintliche
"Schieben nach links" ist Unfug, da die Segmentregister zur internen
Adressberechnung einfach von Bit 4 bis Bit 19 eingesetzt werden, und
danach das Offset dazuaddiert wird:

Adresse = SegmentRegister * 16 + Offset

Ich war bei meiner Berechnung davon ausgegangen, dass das Segmentre-
gister erst in das obere Wort eines 32 Bit breiten Registers kopiert
und dann um 12 Bit nach rechts verschoben wird (was mit x-beliebigen
Inhalten der Segmentregister funktioniert und keine Überläufe verur-
sachen kann), und dann das Offset addiert wird.


> und
>
> FFFF:FFFF = FFFF0 + FFFF = 10FFEF
>
> (da ist man dann tatsächlich jenseits von 1MB, was bei 286 und später
> auch funktioniert (für die Kompatibilität zum 8086 sorgt(e) das
> berüchtigte A20-Gate))


Ohne A20 existiert das führende 21. Bit aber nicht, und nach 0x000FFFFF
kommt 0x00000000 - der 8086/8088 hatte nur 20 Adressleitungen, und sein
Verhalten wurde aus Kompatibilitätsgründen bis heute fortgeführt. D.h.,
dass auch aktuelle Prozessoren unter DOS ohne freigeschaltetes A20-Gate
nur 1 MB adressieren können.

Jens Kallup

unread,
Jun 23, 2020, 7:39:01 PM6/23/20
to
Am 23.06.20 um 22:06 schrieb Bernhard Schornak:
> Ohne A20 existiert das führende 21. Bit aber nicht, und nach 0x000FFFFF
> kommt 0x00000000 - der 8086/8088 hatte nur 20 Adressleitungen, und sein
> Verhalten wurde aus Kompatibilitätsgründen bis heute fortgeführt. D.h.,
> dass auch aktuelle Prozessoren unter DOS ohne freigeschaltetes A20-Gate
> nur 1 MB adressieren können.

Dann ist dieses HIMEM gedöns 32 Bit?

Jens

Jens Kallup

unread,
Jun 23, 2020, 7:46:07 PM6/23/20
to
Am 24.06.20 um 01:38 schrieb Jens Kallup:
> der 8086/8088

hihi, ich glaub ich weiss nun, wo die Bezeichnung 8088
her kommt...
schaut mal in die deutsche mathe Gruppe, da habe ich etwa
zeitgleich ein Posting abgesetzt.
80 - für die 1980er Jahre
88 - für 2x oo (2 mal undendlich)

Die Namensgeber/Erbauer hatten gingen sicherlich davon aus,
dass diese CPU-Reihe erstmal paar jährchen existieren sollte.

Jens

Bernhard Schornak

unread,
Jun 24, 2020, 8:33:18 AM6/24/20
to
Jens Kallup schrieb:
Jein - der 80286 war ein 16-Bit-Prozessor mit einem 24 Bit
breiten Adressbus. Da der -adressierbare- Speicher von der
-Breite- des Adressbusses abhängt, konnte der 8086 nur das
erste MB, der 80286 16 MB, der 80386 sogar die theoretisch
möglichen 4 GB (32 Adress-Bits) ansprechen. Das "A20-Gate"
war ab dem 80286 über ein -externes- Gatter implementiert,
das aus Kompatibilitätsgründen nur von der Software selbst
(z. B. HiMem und die "DOS-Extender") freigeschaltet werden
konnte.

Die "HiMem" ändert das normale Verhalten des 8086, der bei
Adressüberlauf von 0x000FFFFF auf 0x00000000 zurücksprang,
dahingehend, dass Bit 21 (und darauf folgende Bits) gültig
werden, und so Zugriff auf Speicher jenseits des ersten MB
(Adressen größer 0x000FFFFF) ermöglichen.


Grüsse aus Augsburg

Bernhard Schornak

Stefan Reuther

unread,
Jun 24, 2020, 11:41:47 AM6/24/20
to
Am 23.06.2020 um 22:06 schrieb Bernhard Schornak:
> Peter J. Holzer schrieb:
>> On 2020-06-18 13:17, Bernhard Schornak <scho...@web.de> wrote:
>>> 1000:0000 = 00010000 (1000 >> 12 + 0000)
>>>
>>> Segmentregister (CS, DS, ES, SS) enthalten immer das 5. Digit der
>>> Adresse, also 0000.0000 ... 000F.FFFF = 64 kiB * 16 =  1 MiB.
>>
>> Nein, das Segment-Register wird um 4 Positionen nach links geshiftet und
>> dann addiert. Hier macht das keinen Unterschied, weil die unteren 12
>> Bits 0 sind:
>>
>>      1000:0000 = 10000 + 0000 = 10000
>
> CS, DS, ES und SS sind (auch in modernen Prozessoren!) 16 Bit breite
> Register - wenn man 0x1000 in einem 16-Bit breiten Register vier Bit
> nach links schiebt, bleibt Null übrig, und das Überlaufbit wird u.U.
> gesetzt.

Nur dann, wenn man nur 16 Bit hat...

> Die Segmentregister selektieren jeweils einen der 65536 Paragraphen,
> das sind 16-Byte große "Scheibchen" des Speichers. Das vermeintliche
> "Schieben nach links" ist Unfug, da die Segmentregister zur internen
> Adressberechnung einfach von Bit 4 bis Bit 19 eingesetzt werden, und
> danach das Offset dazuaddiert wird:
>
> Adresse = SegmentRegister * 16 + Offset

...dann kann man aber auch nicht mit 16 multiplizieren, denn dabei
fallen auch die überlaufenden Bits weg.

Denn "4 Bits nach links schieben" und "mit 16 multiplizieren" ist das
gleiche. Immer. Bei identischer Breite der verwendeten Recheneinheit,
und das sind halt beim Generieren der Adressen mehr als nur 16 Bits (20
beim 8086, 24 beim 80286, 32 beim 80386).

Und deswegen ist es egal, ob man sagt "Adresse = Segmentregister * 16 +
Offset", oder "Adresse = Segmentregister um 4 bits geschoben, + Offset".

Nicht korrekt ist aber etwas wie "Segmentregister enthalten immer das 5.
Digit der Adresse". 9F00:9000 = A8000, das 'A' kommt in keinem der
Register vor.


Stefan

Jens Kallup

unread,
Jun 24, 2020, 12:46:52 PM6/24/20
to
Am 24.06.20 um 17:38 schrieb Stefan Reuther:
> Nicht korrekt ist aber etwas wie "Segmentregister enthalten immer das 5.
> Digit der Adresse". 9F00:9000 = A8000, das 'A' kommt in keinem der
> Register vor.

Das dann der Videospeicher/Video GPU.
und VGPU haben immer mehr Register?

Jens

Bernhard Schornak

unread,
Jun 24, 2020, 4:23:28 PM6/24/20
to
Stefan Reuther schrieb:


> Am 23.06.2020 um 22:06 schrieb Bernhard Schornak:
>> Peter J. Holzer schrieb:
>>> On 2020-06-18 13:17, Bernhard Schornak <scho...@web.de> wrote:
>>>> 1000:0000 = 00010000 (1000 >> 12 + 0000)
>>>>
>>>> Segmentregister (CS, DS, ES, SS) enthalten immer das 5. Digit der
>>>> Adresse, also 0000.0000 ... 000F.FFFF = 64 kiB * 16 =  1 MiB.
>>>
>>> Nein, das Segment-Register wird um 4 Positionen nach links geshiftet und
>>> dann addiert. Hier macht das keinen Unterschied, weil die unteren 12
>>> Bits 0 sind:
>>>
>>>      1000:0000 = 10000 + 0000 = 10000
>>
>> CS, DS, ES und SS sind (auch in modernen Prozessoren!) 16 Bit breite
>> Register - wenn man 0x1000 in einem 16-Bit breiten Register vier Bit
>> nach links schiebt, bleibt Null übrig, und das Überlaufbit wird u.U.
>> gesetzt.
>
> Nur dann, wenn man nur 16 Bit hat...
>
>> Die Segmentregister selektieren jeweils einen der 65536 Paragraphen,
>> das sind 16-Byte große "Scheibchen" des Speichers. Das vermeintliche
>> "Schieben nach links" ist Unfug, da die Segmentregister zur internen
>> Adressberechnung einfach von Bit 4 bis Bit 19 eingesetzt werden, und
>> danach das Offset dazuaddiert wird:
>>
>> Adresse = SegmentRegister * 16 + Offset
>
> ...dann kann man aber auch nicht mit 16 multiplizieren, denn dabei
> fallen auch die überlaufenden Bits weg.


Verstehendes Lesen hilft hier gewiss weiter... ;)


> Denn "4 Bits nach links schieben" und "mit 16 multiplizieren" ist das
> gleiche.


Nein. Das oberste Nibble eines 16-Bit-Registers um n Bit nach
links schieben heisst, diese n Bit aus dem Register schieben.
Die gespeicherte Information geht dabei verloren. Das 16-Bit-
Register in einer "Adressgeneriermaschine" in die Bits 19 bis
4 zu kopieren erhält den Inhalt des Segmentregisters hingegen
verlustfrei.

Dass man das um vier Bit versetzte "schräg kopieren" auch als
"Multiplikation mit 16" ansehen kann, ist eine Gedankenkrücke
zur leichteren Berechnung, das Verschieben um vier nach links
schon *rein formal* eine falsche Aussage, selbst in dem Fall,
dass dabei mathematisch das selbe herauskommt.

1.

19 18 17 16 15 14 12 11 10 09 08 07 06 05 04 03 02 01 00 EA
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
copy \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
__ __ __ __ 15 14 12 11 10 09 08 07 06 05 04 03 02 01 00 Segment

2.

19 18 17 16 15 14 12 11 10 09 08 07 06 05 04 03 02 01 00 EA
| | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |
__ __ __ __ 15 14 12 11 10 09 08 07 06 05 04 03 02 01 00 Offset
| | | |
Ein "Links" gibt es nur im Zielregister, nicht in den einzel-
nen Quellregistern. Schiebt man die Quellregister nach links,
geht dabei unweigerlich Information verloren. Abgesehen davon
gibt es keinen Befehl "SAL/SHL segReg, n" - ein Compiler wird
solch ein Konstrukt als ungültig zurückweisen.


> Immer. Bei identischer Breite der verwendeten Recheneinheit,
> und das sind halt beim Generieren der Adressen mehr als nur 16 Bits (20
> beim 8086, 24 beim 80286, 32 beim 80386).
>
> Und deswegen ist es egal, ob man sagt "Adresse = Segmentregister * 16 +
> Offset", oder "Adresse = Segmentregister um 4 bits geschoben, + Offset".


Nein. Siehe oben.


> Nicht korrekt ist aber etwas wie "Segmentregister enthalten immer das 5.
> Digit der Adresse". 9F00:9000 = A8000, das 'A' kommt in keinem der
> Register vor.


Ich habe nirgendwo geschrieben, dass das fünfte Digit (= Bits
16 bis 19) -identisch- mit dem obersten Nibble der effektiven
Adresse sein muss. Auch das angedachte Kopieren meines 16 Bit
breiten Wertes in eine -32 Bit breite- Speicherstelle und das
anschließende Verschieben um 12 Bit nach rechts ist eine for-
mal gültige Operation, die die Information nicht invalidiert,
sondern erhält.

Hier der Ansatz eines auf DOS aufgesetzten "Betriebssystems",
das heftigen Gebrauch von der Spielerei mit Segment-Registern
macht:

https://drive.google.com/drive/folders/0B1OgMlxNnSNELTZSTDFzb2RWbmM?usp=sharing

1993 ist schon etwas her, aber die grundlegenden Dinge gelten
bis heute. Sogar das A20 gibt es selbst noch auf den neuesten
Mainboards und Prozessoren... ;)

P.S.: Vorsicht mit den Funktionen meines OS-Ansatzes: Die tun
exakt das, was ihre Namen suggerieren!

Stefan Reuther

unread,
Jun 25, 2020, 12:33:25 PM6/25/20
to
Am 24.06.2020 um 22:23 schrieb Bernhard Schornak:
> Stefan Reuther schrieb:
>> Am 23.06.2020 um 22:06 schrieb Bernhard Schornak:
>>> Peter J. Holzer schrieb:
>>>> Nein, das Segment-Register wird um 4 Positionen nach links geshiftet
>>>> und
>>>> dann addiert. Hier macht das keinen Unterschied, weil die unteren 12
>>>> Bits 0 sind:
>>>>
>>>>       1000:0000 = 10000 + 0000 = 10000
>>>
>>> CS, DS, ES und SS sind (auch in modernen Prozessoren!) 16 Bit breite
>>> Register - wenn man 0x1000 in einem 16-Bit breiten Register vier Bit
>>> nach links schiebt, bleibt Null übrig, und das Überlaufbit wird u.U.
>>> gesetzt.
>>
>> Nur dann, wenn man nur 16 Bit hat...
>>
>>> Die Segmentregister selektieren jeweils einen der 65536 Paragraphen,
>>> das sind 16-Byte große "Scheibchen" des Speichers. Das vermeintliche
>>> "Schieben nach links" ist Unfug, da die Segmentregister zur internen
>>> Adressberechnung einfach von Bit 4 bis Bit 19 eingesetzt werden, und
>>> danach das Offset dazuaddiert wird:
>>>
>>> Adresse = SegmentRegister * 16 + Offset
>>
>> ...dann kann man aber auch nicht mit 16 multiplizieren, denn dabei
>> fallen auch die überlaufenden Bits weg.
>
> Verstehendes Lesen hilft hier gewiss weiter... ;)

Das Kompliment geb ich zurück.

>> Denn "4 Bits nach links schieben" und "mit 16 multiplizieren" ist das
>> gleiche.
>
> Nein. Das oberste Nibble eines 16-Bit-Registers um n Bit nach
> links schieben heisst, diese n Bit aus dem Register schieben.

Das ist deine und nur deine Definition.

Intels Definition der Adressgenerierung im Real Mode hingegen ist:

# 14.1 Physical Address Formation
#
# The 80386 provides a one Mbyte + 64 Kbyte memory space for an 8086
# program. Segment relocation is performed as in the 8086: the 16-bit
# value in a segment selector is shifted left by four bits to form the
^^^^^^^^^^^^^^^^^^^^^^^^^
# base address of a segment. The effective address is extended with four
# high order zeros and added to the base to form a linear address as
# Figure 14-1 illustrates.

("INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986", z.B. hier erhältlich:
<http://download.xskernel.org/docs/processors/intel/386/386intel.txt>)

Intel geht dabei sogar ganz selbstverständlich davon aus, dass die
Addition zweier 20-Bit-Werte einen 21-Bit-Wert ergibt.

>> Nicht korrekt ist aber etwas wie "Segmentregister enthalten immer das 5.
>> Digit der Adresse". 9F00:9000 = A8000, das 'A' kommt in keinem der
>> Register vor.
>
> Ich habe nirgendwo geschrieben, dass das fünfte Digit (= Bits
> 16 bis 19) -identisch- mit dem obersten Nibble der effektiven
> Adresse sein muss.

Du hast wörtlich geschrieben: "Segmentregister enthalten immer das 5.
Digit der Adresse". Wie man das anders interpretieren kann als "das
fünfte Digit ist identisch mit dem obersten Nibble der Adresse" ist mir
ein Rätsel.

Man muss es ja nun nicht schwerer machen als es ist. Effektive Adresse =
16*Segment + Offset. Fertig.


Stefan

Bernhard Schornak

unread,
Jun 26, 2020, 5:35:52 AM6/26/20
to
Stefan Reuther schrieb:
Ach? Schiebebefehl visuell anschaulich dargestellt:

http://www.c-jump.com/CIS77/ASM/Flags/F77_0140_shl_sal_instructions.htm


Dokumentation der Prozessorhersteller (nicht ganz so anschaulich):

http://developer.amd.com/wordpress/media/2008/10/24594_APM_v3.pdf

=> Seite 306 - SAL/SHL

https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4.html

=> Vol. 2B 4-590 bis 4-594 Vol. 2B - SAL/SAR/SHL/SHR—Shift


> Intels Definition der Adressgenerierung im Real Mode hingegen ist:
>
> # 14.1 Physical Address Formation
> #
> # The 80386


Ist kein 8086. Das hier

https://edge.edx.org/c4x/BITSPilani/EEE231/asset/8086_family_Users_Manual_1_.pdf

ist ein 8086. Passend zum Thema: Seiten 2-7 ff.

Bild 2-18 auf Seite 2-13 ist wohl die Ursache für die später entstandene
Missdeutung, dass die Segmentregister "nach Links geschoben" würden. Das
Bild bestätigt aber unzweideutig, dass tatsächlich das von mir in meinem
letzten Post geschilderte Verfahren (das um vier Bit versetzte Kopieren)
zum Einsatz kam. Die linke Seite zeigt das interne Register, in dem alle
Adressen generiert werden, die rechte Seite Offset- und Segmentregister.
Dieses versetzte Kopieren war damals hardwaremäßig wesentlich schneller,
als die langsame Bitschieberei: Der 8086 benötigte m. W. pro geschobenem
Bit einen vollen Taktzyklus, für vier Bit wären also 4 Takte "verbraten"
worden. Abgesehen davon (wie bereits im letzten Post erwähnt!) existiert
kein Schiebebefehl für Segmentregister. Außer MOV, PUSH und POP ist kein
einziger "general purpose" Befehl für Segmentregister zulässig.

P.S.: Auch die von Dir zitierten "Segmentselektoren" werden nicht selbst
manipuliert (geschoben, multipliziert, et cetera), sondern in einen Teil
der AGU (Address Generation Unit) kopiert. Erst dort wird die Kopie nach
Bedarf bearbeitet, um eine gültige Adresse zu erzeugen. Aber selbst hier
gilt, dass man keine Schiebeoperation ausführt, wenn man die Aufgabe mit
Bit-versetzem Kopieren lösen kann (kostet keinen Extra-Zyklus).


>>> Nicht korrekt ist aber etwas wie "Segmentregister enthalten immer das 5.
>>> Digit der Adresse". 9F00:9000 = A8000, das 'A' kommt in keinem der
>>> Register vor.
>>
>> Ich habe nirgendwo geschrieben, dass das fünfte Digit (= Bits
>> 16 bis 19) -identisch- mit dem obersten Nibble der effektiven
>> Adresse sein muss.
>
> Du hast wörtlich geschrieben: "Segmentregister enthalten immer das 5.
> Digit der Adresse". Wie man das anders interpretieren kann als "das
> fünfte Digit ist identisch mit dem obersten Nibble der Adresse" ist mir
> ein Rätsel.


Das fünfte Digit bestimmt (zusammen mit den Digits Drei bis Eins) ja den
selektierten Paragraphen, zu dem noch das Offset addiert werden muss, um
die gültige Adresse zu erhalten. Das ändert nichts an der Tatsache, dass
ein Segmentregister immer die Digits Vier bis Eins enthält. Würde es das
Digit Null der Adresse enthalten, wäre es kein Segment- sondern ein Off-
setregister. Ich sehe hier ehrlich gesagt keinen Spielraum für jedwelche
Interpretationen. Abgesehen davon: Du interpretierst, ich aber weiß, was
ich geschrieben habe... (Ich räume ein, dass ich nicht davon ausgegangen
war, das jemand sich an einzelnen Worten aufhängt, sonst hätte ich alles
gerichtsfest formuliert.)

Um weiteren Missverständnissen vorzubeugen: Das "fünfte Digit" ist Digit
Nummer vier, da wir das Zählen bei Digit Nummer Null beginnen. Ein Digit
ist eine Ziffer, die Teil einer Zahl ist. Im hier besprochenen Fall geht
es um eine fünfstellige Hexadezimalzahl, deren einzelne Digits die Werte
"0" bis "F" (dezimal 0 - 15) annehmen können. Die Digits sind wie folgt

Digit 4 - Digit 3 - Digit 2 - Digit 1 - Digit 0

durchnummeriert. Digit 4 ist das fünfte, Digit 3 das vierte, Digit 2 das
dritte, Digit 1 das zweite und Digit 0 das erste Digit.


> Man muss es ja nun nicht schwerer machen als es ist. Effektive Adresse =
> 16*Segment + Offset. Fertig.


Und worin unterscheidet sich das nun von meiner am 23.06.2020 geposteten
Aussage "Adresse = SegmentRegister * 16 + Offset"? ;)

Um es noch einmal deutlich zu machen: Es geht mir *einzig und allein* um
die Formalie, dass man in 16-Bit-Registern 20 Bit breite Daten weder ab-
legen noch manipulieren kann. Das von iNTEL fälschlicherweise angeführte
"shift left 4 bits" führt zwar - ebenso wie eine Vielzahl anderer Wege -
zum korrekten Ergebnis, ist aber nicht das, was sich auf *Hardwareebene*
tatsächlich abspielt.

Mag sein, dass sich das nur Leuten erschließt, die mit TTL und CMOS groß
geworden sind...

Peter J. Holzer

unread,
Jun 26, 2020, 12:39:53 PM6/26/20
to
On 2020-06-24 20:23, Bernhard Schornak <scho...@web.de> wrote:
> Stefan Reuther schrieb:
>> Am 23.06.2020 um 22:06 schrieb Bernhard Schornak:
>> Denn "4 Bits nach links schieben" und "mit 16 multiplizieren" ist das
>> gleiche.
>
>
> Nein. Das oberste Nibble eines 16-Bit-Registers um n Bit nach
> links schieben heisst, diese n Bit aus dem Register schieben.
> Die gespeicherte Information geht dabei verloren.

Aber beim 12 Bit nach rechts schieben fantasierst Du ein
nicht-existierendes 32-Bit-Register dazu, um genau das zu verhindern.
Ist schon klar.

hp

Stefan Reuther

unread,
Jun 26, 2020, 12:41:17 PM6/26/20
to
Am 26.06.2020 um 11:35 schrieb Bernhard Schornak:
> Stefan Reuther schrieb:
>>>> Denn "4 Bits nach links schieben" und "mit 16 multiplizieren" ist das
>>>> gleiche.
>>>
>>> Nein. Das oberste Nibble eines 16-Bit-Registers um n Bit nach
>>> links schieben heisst, diese n Bit aus dem Register schieben.
>>
>> Das ist deine und nur deine Definition.
>
> Ach? Schiebebefehl visuell anschaulich dargestellt:

Der Schiebebefehl ist an der Adressgenerierung nicht beteiligt.

> Dokumentation der Prozessorhersteller (nicht ganz so anschaulich):
>
> http://developer.amd.com/wordpress/media/2008/10/24594_APM_v3.pdf
>
> => Seite 306 - SAL/SHL

Da steht, dass der Befehl zwei Dinge tut: "Shifts the bits...",
"...discards bits shifted out...". Das verwerfen der rausgeschobenen
Bits ist also kein intrinsisches Verhalten der Operation "shift".

>> Intels Definition der Adressgenerierung im Real Mode hingegen ist:
>>
>> # 14.1  Physical Address Formation
>> #
>> # The 80386
>
> Ist kein 8086. Das hier
>
> https://edge.edx.org/c4x/BITSPilani/EEE231/asset/8086_family_Users_Manual_1_.pdf
>
> ist ein 8086. Passend zum Thema: Seiten 2-7 ff.
>
> Bild 2-18 auf Seite 2-13 ist wohl die Ursache für die später entstandene
> Missdeutung, dass die Segmentregister "nach Links geschoben" würden.

"shift left 4 bits" ist ziemlich eindeutig.

> Die linke Seite zeigt das interne Register, in dem alle
> Adressen generiert werden, die rechte Seite Offset- und Segmentregister.
> Dieses versetzte Kopieren war damals hardwaremäßig wesentlich schneller,
> als die langsame Bitschieberei: Der 8086 benötigte m. W. pro geschobenem
> Bit einen vollen Taktzyklus, für vier Bit wären also 4 Takte "verbraten"
> worden. Abgesehen davon (wie bereits im letzten Post erwähnt!) existiert
> kein Schiebebefehl für Segmentregister. Außer MOV, PUSH und POP ist kein
> einziger "general purpose" Befehl für Segmentregister zulässig.

Du haust immer wieder "die mathematische Operation 'shift'" und "den
Prozessorbefehl 'shift'" durcheinander. Warum soll ich, wenn ich ein
Stück Silizium baue, händisch irgendwelche Daten durch eine ALU fummeln,
wenn ich einfach ein paar Drähte schief anlöten kann?

[weitere Verkomplizierungen gelöscht]

>> Man muss es ja nun nicht schwerer machen als es ist. Effektive Adresse =
>> 16*Segment + Offset. Fertig.
>
> Und worin unterscheidet sich das nun von meiner am 23.06.2020 geposteten
> Aussage "Adresse = SegmentRegister * 16 + Offset"? ;)
>
> Um es noch einmal deutlich zu machen: Es geht mir *einzig und allein* um
> die Formalie, dass man in 16-Bit-Registern 20 Bit breite Daten weder ab-
> legen noch manipulieren kann.

Das hat ja auch niemand außer dir behauptet.

> Das von iNTEL fälschlicherweise angeführte
> "shift left 4 bits" führt zwar - ebenso wie eine Vielzahl anderer Wege -
> zum korrekten Ergebnis, ist aber nicht das, was sich auf *Hardwareebene*
> tatsächlich abspielt.

"Ein Geisterfahrer? Hunderte!"

> Mag sein, dass sich das nur Leuten erschließt, die mit TTL und CMOS groß
> geworden sind...

Also wenn ich einen Wert vor dem Addieren um 4 Stellen nach links
shiften will, bau ich keinen Shifter ein, sondern löte die Drähte
passend an den Addierer.

Das gleiche macht(e) Intel in ihrem Prozessor. Und deswegen haben sie
auch kein Problem damit, dass das mit einem 'shl'-Befehl in einem
16-Bit-Register nicht funktionieren würde.


Stefan

Bernhard Schornak

unread,
Aug 6, 2020, 3:29:03 AM8/6/20
to
Stefan Reuther schrieb:


> Am 26.06.2020 um 11:35 schrieb Bernhard Schornak:
>> Stefan Reuther schrieb:
>>>>> Denn "4 Bits nach links schieben" und "mit 16 multiplizieren" ist das
>>>>> gleiche.
>>>>
>>>> Nein. Das oberste Nibble eines 16-Bit-Registers um n Bit nach
>>>> links schieben heisst, diese n Bit aus dem Register schieben.
>>>
>>> Das ist deine und nur deine Definition.
>>
>> Ach? Schiebebefehl visuell anschaulich dargestellt:
>
> Der Schiebebefehl ist an der Adressgenerierung nicht beteiligt.


Um diese Aussage hier geht es:

<"Nein, das Segment-Register wird um 4 Positionen nach links geshiftet
und dann addiert."> - Peter J. Holzer, 23.06.2020, 11:31.

Du bestätigst mit Deiner Aussage also meine bisherigen Ausführungen -
es stellt sich dann natürlich die Frage, welchen Sinn eine Diskussion
haben mag, in der Du mir vorwirfst, *genau das* geschrieben zu haben,
was Du immer dann zugibst, wenn es Dir gerade in den Kram passt, aber
immer dann abstreitest, wenn *ich* es ausführe.


>> Dokumentation der Prozessorhersteller (nicht ganz so anschaulich):
>>
>> http://developer.amd.com/wordpress/media/2008/10/24594_APM_v3.pdf
>>
>> => Seite 306 - SAL/SHL
>
> Da steht, dass der Befehl zwei Dinge tut: "Shifts the bits...",
> "...discards bits shifted out...". Das verwerfen der rausgeschobenen
> Bits ist also kein intrinsisches Verhalten der Operation "shift".


Ich habe mir erlaubt, den Begriff "intrinsisch" für Dich zu suchen:

https://de.wikipedia.org/wiki/Intrinsische_Funktion
https://de.wikipedia.org/wiki/Motivation#Intrinsische_Quellen

Da unsere Quellen erkenntnistechnisch nichts zur Diskussion beitragen
können, gelten die hier

https://de.wikipedia.org/wiki/Bitweiser_Operator#Bitweise_Verschiebungen

geschilderten Zusammenhänge, womit Deine Aussage

<Das verwerfen der rausgeschobenen Bits ist also kein intrinsisches
Verhalten der Operation "shift">

falsifiziert ist. Dass Du hier ein Oxymoron konstruiert hast, ist Dir
sicher aufgefallen:

Die von AMD veröffentlichte Definition des SAL/SHL-Befehls

"Shifts the bits of a register or memory location (first operand) to the
left through the CF bit by the number of bit positions in an unsigned
immediate value or the CL register (second operand). The instruction
discards bits shifted out of the CF flag. For each bit shift, the SAL
instruction clears the least-significant bit to 0."

und die von iNTEL verfasste

"Shifts the bits in the first operand (destination operand) to the left
or right by the number of bits specified in the second operand (count
operand). Bits shifted beyond the destination operand boundary are first
shifted into the CF flag, then discarded. At the end of the shift
operation, the CF flag contains the last bit shifted out of the
destination operand."

widersprechen Deiner Aussage

"Das verwerfen der rausgeschobenen Bits ist also kein intrinsisches
[= innewohnendes, inhärentes (B.S.)] Verhalten der Operation "shift""

diametral, da das Verwerfen der hinausgeschobenen Bits sehr wohl eine
jedem Schiebebefehl innewohnende/inhärente/intrinsische *Eigenschaft*
ist. Ein von Dir in den Raum gestelltes "extrinsisches Verhalten" ist
weder mit der Definition des SAL/SHL-Befehls der Prozessorhersteller,
noch mit der Realität der Assemblerprogrammierung kongruent.


>>> Intels Definition der Adressgenerierung im Real Mode hingegen ist:
>>>
>>> # 14.1  Physical Address Formation
>>> #
>>> # The 80386
>>
>> Ist kein 8086. Das hier
>>
>> https://edge.edx.org/c4x/BITSPilani/EEE231/asset/8086_family_Users_Manual_1_.pdf
>>
>> ist ein 8086. Passend zum Thema: Seiten 2-7 ff.
>>
>> Bild 2-18 auf Seite 2-13 ist wohl die Ursache für die später entstandene
>> Missdeutung, dass die Segmentregister "nach Links geschoben" würden.
>
> "shift left 4 bits" ist ziemlich eindeutig.


Nur dann, wenn man den Inhalt der Zeichnung willentlich ausblendet...

Der Pfeil vom Segmentregister zur AGU zeigt aber nun einmal eindeutig
eine um vier Bit nach Links versetzte Kopieraktion (auf diese bezieht
sich das "shift left 4 bits"), und keine Schiebeoperation *innerhalb*
des Segmentregisters mit anschließendem Kopiervorgang. Wenn Du diesen
eindeutigen Sachverhalt und eine in allen Handbüchern für Prozessoren
eingebürgerte Zeichenkonvention abstreiten musst, um in einer Debatte
ein Gegenargument passend biegen zu können, solltest Du die Intention
hinter Deinem Tun vielleicht einmal selbstkritisch hinterfragen...


>> Die linke Seite zeigt das interne Register, in dem alle
>> Adressen generiert werden, die rechte Seite Offset- und Segmentregister.
>> Dieses versetzte Kopieren war damals hardwaremäßig wesentlich schneller,
>> als die langsame Bitschieberei: Der 8086 benötigte m. W. pro geschobenem
>> Bit einen vollen Taktzyklus, für vier Bit wären also 4 Takte "verbraten"
>> worden. Abgesehen davon (wie bereits im letzten Post erwähnt!) existiert
>> kein Schiebebefehl für Segmentregister. Außer MOV, PUSH und POP ist kein
>> einziger "general purpose" Befehl für Segmentregister zulässig.
>
> Du haust immer wieder "die mathematische Operation 'shift'" und "den
> Prozessorbefehl 'shift'" durcheinander. Warum soll ich, wenn ich ein
> Stück Silizium baue, händisch irgendwelche Daten durch eine ALU fummeln,
> wenn ich einfach ein paar Drähte schief anlöten kann?


Suche nach "mathematische Operationen":

=> Weiterleitung auf https://de.wikipedia.org/wiki/Grundrechenart
https://de.wikipedia.org/wiki/Operator_%28Mathematik%29
https://www.etsc.uni-kl.de/wbt/MatlabTutorial/233/index.html

Das Konstrukt "die mathematische Operation 'shift'" solltest Du viel-
leicht in der Esoterik-Gruppe Deiner Wahl diskutieren?

Für diese NG gelten selbstverständlich die hier

https://de.wikipedia.org/wiki/Bitweiser_Operator#Bitweise_Verschiebungen

dargelegten Definitionen...


> [weitere Verkomplizierungen gelöscht]
>
>>> Man muss es ja nun nicht schwerer machen als es ist. Effektive Adresse =
>>> 16*Segment + Offset. Fertig.
>>
>> Und worin unterscheidet sich das nun von meiner am 23.06.2020 geposteten
>> Aussage "Adresse = SegmentRegister * 16 + Offset"? ;)
>>
>> Um es noch einmal deutlich zu machen: Es geht mir *einzig und allein* um
>> die Formalie, dass man in 16-Bit-Registern 20 Bit breite Daten weder ab-
>> legen noch manipulieren kann.
>
> Das hat ja auch niemand außer dir behauptet.


Um diese Aussage hier geht es:

<"Nein, das Segment-Register wird um 4 Positionen nach links geshiftet
und dann addiert."> - Peter J. Holzer, 23.06.2020, 11:31.

Deine Unterstellung, *ich* hätte diese Aussage in einem meiner Posts
gemacht, darfst Du gern anhand einer Angabe des Datums und der Zeit,
zu der ich das geschrieben haben soll, belegen.

Deine Aussage ist - ungeachtet des noch zu erbringenden Nachweises -
allein durch diesen Verweis auf Peter J. Holzers Post falsifiziert.


>> Mag sein, dass sich das nur Leuten erschließt, die mit TTL und CMOS groß
>> geworden sind...
>
> Also wenn ich einen Wert vor dem Addieren um 4 Stellen nach links
> shiften will, bau ich keinen Shifter ein, sondern löte die Drähte
> passend an den Addierer.
>
> Das gleiche macht(e) Intel in ihrem Prozessor. Und deswegen haben sie
> auch kein Problem damit, dass das mit einem 'shl'-Befehl in einem
> 16-Bit-Register nicht funktionieren würde.


Die Gesamtheit Deiner Ausführungen ist inkonsistent und unehrlich, da
Du Dir laufend selbst widersprichst. Die Erfindung eines esoterischen
Konstrukts der Marke

<"die mathematische Operation 'shift'">

hilft auch nicht weiter, da wir hier in einer NG für Assemblersprache
diskutieren - der Begriff "Shift" bezieht sich also eindeutig auf die
(meines Wissens) bei allen Prozessorfamilien implementierten Schiebe-
befehle, die in einem Register oder im Speicher entweder das MSB nach
Links oder das LSB nach Rechts in das Überlauf-Flag schieben und eine
Null (bei zeichenbehafteten Datentypen kann, in Abhängigkeit vom Pro-
zessortyp und Schiebebefehl, auch das Vorzeichenbit verwendet werden)
in das LSB (SAL/SHL) oder MSB (SAR/SHR) hineinschieben. Auf spezielle
Formen des Schiebens - namentlich Bitrotation - muss ich nicht einge-
hen, da sie für die *Adressgeneration* untauglich sind.

Für Deine "mathematische Operation 'shift'" gibt es in der Mathematik
übrigens einen eindeutigen Operator namens *Multiplikation* - weshalb
also neue und extrem unpassende Namen für etwas erfinden, das bereits
einen verbindlichen Namen hat?

Da euch beiden bis jetzt nichts eingefallen ist, was uns bislang noch
unbekannte Erkenntnisse hätte vermitteln können, sehe ich unsere Dis-
kussion hiermit als abgeschlossen an - weder Deine an den Haaren her-
beigezogenen Wortschöpfungen noch Peters Verständnislosigkeit simpler
Sachverhalte haben das Potenzial, meine Aufmerksamkeit noch länger zu
binden. Zudem habt ihr beide mich davon überzeugt, diese eh schon vor
mindestens einem Jahrzehnt gestorbene NG fortan zu ignorieren. Ausser
Jens postet hier niemand mehr, und der kann ebenso per E-mail fragen,
wenn er Hilfe benötigt. Das Leben ist zu kurz, um es mit Belanglosig-
keiten zu verplempern.


Viel Spaß wünscht

Bernhard Schornak

Bernhard Schornak

unread,
Aug 6, 2020, 3:29:55 AM8/6/20
to
Peter J. Holzer schrieb:
Bleiben wir beim tatsächlich geschriebenen Text:

>>>> Jens Kallup schrieb:
>>>>
>>>>> Mal angenommen, das segment 0x1000 mit offset 0x0000, also 1000:0000
>>>>> oder linear 0x10000000
>>>>
>>>> 1000:0000 = 00010000 (1000 >> 12 + 0000)

Meine Ausführung -übernimmt- die Schreibweise des OP und zeigt einen
*gültigen* Lösungsweg zur Berechnung der an den Adressbus geleiteten
Adresse auf.

Die Schreibweise "1000:0000" ist weder auf Register noch in Hardware
implementierten, konkreten "Speicherplatz" bezogen - es handelt sich
um eine Konvention, ähnlich der Konvention, dass Eins plus Eins Zwei
ergibt (eine *per Konsens* festgelegte Übereinkunft). Ich führe also
nichts hinzu, was nicht bereits da war, und stelle auch keine ungül-
tigen Berechnungen an.

Deine auf diese (fachlich korrekte!) Aussage gepostete Antwort

<"Nein, das Segment-Register wird um 4 Positionen nach links geshiftet
und dann addiert."> - Peter J. Holzer, 23.06.2020, 11:31.

hingegen ist faktisch falsch, da Segmentregister 16 und nicht 20 Bit
breit sind, und beim "Shiften nach Links" unweigerlich Informationen
(das komplette oberste Nibble) verloren gehen. Es geht hier nicht um
die Frage, ob man den *Inhalt* des Segmentregisters 4 Bit nach Links
schieben kann, was einer -Multiplikation- mit 16 entspräche, sondern
einzig und allein darum, dass man das nicht - wie Du es behauptest -
*im* Segmentregister tun kann, da man sonst das ganze oberste Nibble
aus dem Segmentregister schieben würde, was eine -ungültige Adresse-
ergäbe.

Ihr zwei könnt euch gern noch ein paar Freunde zur Verstärkung dazu-
holen, dadurch wird Deine Aussage aber weder wahrer noch richtiger.
0 new messages