Brueggi hat geschrieben:Leider habe ich mein Assemblerbuch nicht zur Hand (verliehen). Was für NOPs gibt es denn noch?
"Wolfgang Kern" in Newsgroup "alt.lang.asm":
http://coding.derkeiler.com/Archive/Ass ... 00073.html
X86 code optimisation guide, App F /NOP (latency=0):
Note 7: These instructions have an effective latency of that which is
listed.
They map to internal NOPs that can be executed at a rate of three per cycle
and do not occupy execution resources.
____________________________________________
Software Optimisation Guide Athlon 10-Family App C2 /NOP(latency~0):
Note 4: The NOP instruction does not consume any execution resources.
________________________________________________
Software Optimization Guide for AMD64 Processors
Chapter 4.12:
Code Padding with Operand-Size Override and NOP
(applies to 32-bit code as well)
NOP1_OVERRIDE_NOP TEXTEQU <DB 090h>
NOP2_OVERRIDE_NOP TEXTEQU <DB 066h,090h>
NOP3_OVERRIDE_NOP TEXTEQU <DB 066h,066h,090h>
NOP4_OVERRIDE_NOP TEXTEQU <DB 066h,066h,066h,090h>
NOP5_OVERRIDE_NOP TEXTEQU <DB 066h,066h,090h,066h,090h>
NOP6_OVERRIDE_NOP TEXTEQU <DB 066h,066h,090h,066h,066h,090h>
NOP7_OVERRIDE_NOP TEXTEQU <DB 066h,066h,066h,090h,066h,066h,090h>
NOP8_OVERRIDE_NOP TEXTEQU <DB 066h,066h,066h,090h,066h,066h,066h,090h>
NOP9_OVERRIDE_NOP TEXTEQU <DB 066h,066h,090h,066h,066h,090h,066h,066h,090h>
James Harris:
* 0x66 prefix bytes are not generally the way to go on Intel CPUs,
* it would be good to get to the bottom of why 3, 4 and, to some
extent, 6 nops improved code speed.
Question regarding the (x86) assembler's use of NOP
http://mail.openjdk.java.net/pipermail/ ... 03881.html
The Intel Arch Optimization Guide recommends the following regarding NOPs:
3.5.1.8 Using NOPs
Code generators generate a no-operation (NOP) to align instructions.
Examples of NOPs of different lengths in 32-bit mode are shown below:
1-byte: XCHG EAX, EAX
2-byte: 66 NOP
3-byte: LEA REG, 0 (REG) (8-bit displacement)
4-byte: NOP DWORD PTR [EAX + 0] (8-bit displacement)
5-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (8-bit displacement)
6-byte: LEA REG, 0 (REG) (32-bit displacement)
7-byte: NOP DWORD PTR [EAX + 0] (32-bit displacement)
8-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (32-bit displacement)
9-byte: NOP WORD PTR [EAX + EAX*1 + 0] (32-bit displacement)
Ich kenne sowas nur vom 6510, wo es verschieden "lange" (von den Bytes her) NOPs gibt. Ok, solche Optimierungsmethoden sind für Grafik/Games sicher super, doch glaub ich nicht, dass es bei einer 08/15-Anwendung (oder einem DOS) sinn macht, wenn 99% der Zeit damit verbracht wird, auf Eingaben zu warten.
Beim Warten auf eine Eingabe macht es bestimmt keinen Sinn, aber in Anwendung wo zeitkritische Routinen verwendet werden.
Ich bin mir sicher, das ich da das ein oder andere noch stark optimieren kann - doch das sind dann meistens stellen, die nur einmal (bei FileOpen) am Anfang aufgerufen werden, während die Zeit dann wieder drauf geht, von Datenträger zu lesen

Und da alles am 80286 laufen soll, macht eine Optimierung auf 386/486 usw. auch keinen sinn.
Nachdem man es am Anfang überprüft hat welche CPU vorhanden ist, könnte man für wenige zeitkritische Routinen für 80286 einen anderen optimierten Code verwenden, als für 80386 und beide solcher optimierten Routinen zur Auswahl mitbringen. Ich denke besonders auf älteren Rechnern macht eine Optimierung für verschiedene CPU-Modelle Sinn.
Subroutine zum Ermitteln der CPU:
Code: Alles auswählen
Cpu86 = 0
Cpu286 = 4
Cpu386 = 8
Cpu486 = 12
Cpu586 = 16
;-------------------------------------
GETCPU: mov ax, Cpu86
xor bx, bx
push bx ; Null auf Stack
popf ; Null in Flagregister
pushf
pop bx ; zurück nach bx
and bh, 0F0h
cmp bh, 0F0h ; wenn gleich, dann 8086
je short CPUOK
;-------------------------------------
mov ax, Cpu286
push 7000h ; dasselbe mit 7000h
popf
pushf
pop bx
and bh, 70h
jz short CPUOK
;-------------------------------------
mov ax, Cpu386
mov edx, esp
and esp, 0FFFCh ; durch vier teilbare Adr.
pushfd
pop ebx
mov ecx, ebx
btc ebx, 18 ; Bit 18 umdrehen
push ebx
popfd
pushfd
pop ebx
push ecx ; alte Flaggen zurück
popfd
mov esp, edx ; Stack zurück
cmp ecx, ebx ; wenn gleich dann 386
jz short CPUOK
;-------------------------------------
mov ax, Cpu486
btc ecx, 21
push ecx
popfd
pushfd
pop ebx
cmp ebx, ecx ; wenn ungleich, dann 486
jnz short CPUOK
mov ax, Cpu586 ; sonst Pentium
CPUOK: mov bp, ax
ret ; AX=Cpu
Über prefetch queue:
http://www.phatcode.net/res/224/files/h ... 11-02.html
http://www.rcollins.org/secrets/PrefetchQueue.html
The 80386 is documented as having a 16-byte prefetch queue. At one time, it did, but due to a bug in the pipelining architecture, Intel had to abandon the 16-byte queue, and only use a 12-byte queue. The change occurred (I believe) between the D0, and D1 step of the '386. The '386SX wasn't affected by the bug, and therefore hasn't changed.
What is prefetch queue in 8086?
http://wiki.answers.com/Q/What_is_prefe ... ue_in_8086
To speed up the program execution, the B.I.U fetches six instructions byte ahead of time from memory and stores in FIFO registers called "queue".
Wie reagiert eigentlich ein 386er auf einen für 286er optimierten Code, stichwort Prefetch-Queue z. B. ? Gibts dann einen Einbruch?
Ich vermute ein für den 286er optimierten Code wird auch auf einem 386er schneller ausgeführt, als ein 286er Code der nicht optimiert wurde.
Example program to detect the size of the PIQ.
http://en.wikipedia.org/wiki/Prefetch_input_queue
This is an example NASM-syntax self-modifying x86-assembly algorithm that determines the size of the PIQ:
Code: Alles auswählen
ode_starts_here:
xor cx, cx ; zero register cx
xor ax, ax ; zero register ax
mov dx, cs
mov [code_segment], dx ; "calculate" codeseg in the far jump below (edx here too)
around:
cmp ax, 1 ; check if ax has been alterd
je found_size
mov [nop_field+cx], 0x90 ; 0x90 = opcode "nop" (NO oPeration)
inc cx
db 0xEA ; 0xEA = opcode "far jump"
dw flush_queue ; should be followed by offset (rm = "dw", pm = "dd")
code_segment:
dw 0 ; and then the code segment (calculated above)
flush_queue:
mov [nop_field+cx], 0x40 ; 0x40 = opcode "inc ax" (INCrease ax)
nop_field:
nop times 256
jmp around
found_size:
;
; register cx now contains the size of the PIQ
; this code is for real mode and 16-bit protected mode, but it could easily be changed into
; running for 32-bit protected mode as well. just change the "dw" for
; the offset to "dd". you need also change dx to edx at the top as
; well. (dw and dx = 16 bit addressing, dd and edx = 32 bit addressing)
;
Leistungssteigerung durch das Pipelining.
http://de.wikipedia.org/wiki/Pipeline_(Prozessor)
Trotzdem: Ich finds äußert interessant - Du könntest zum Thema optimierung ja mal eine Art "Trickkiste" zusammenstellen (falls es die nicht schon hier gibt und ich es nicht bemerkt hab). Echt cool, was Du so drauf hast

Ja stimmt so eine "Trickkiste" wäre nicht schlecht.
Dirk