[x86] [GCC] Zusätzliche NOP Instruktion im Maschinencode

Hallo Community,


Hab ein Verständnisproblem mit dem erzeugten Maschinencode vom GCC.

Ich bin eigentlich immer davon ausgegangen, dass der zusätzliche NOP Befehl zu Alignment Zwecken hinzugefügt wird.
Damit der Prozessor nicht auf ungerade Adressen springen muss. Dachte ich zu mindestens bisher.
Jedenfalls ist das mit GCC nicht der Fall (siehe objdump -d Anhang).

Jetzt zur Frage:
Für was wird der zusätzliche NOP Befehl manchmal eingefügt, wenn dem Prozessor anscheinend egal ist wenn die Sprungadresse ungerade ist?
 

Anhänge

  • dump.txt
    13,5 KB · Aufrufe: 5
Der Linker fügt die NOPs ein um den Code auf 8/16/32 Bytes zu alignen, da die meisten Prozessoren in diesen Schritten Code in die Prefetch Queue laden, werden die Funktions Entry Points auf z.B. 16 Bytes aligned, um möglichst viel wichtigen Code auf einmal einlesen zu können.
Mit der optin -fno-align-functions kann man das auch testweise abschalten.
 
Okay, dass der Linker die NOP Instruktionen einfügt wusste ich nicht.

Aber im obigen Anhang hab ich das Alignment nicht ausgeschaltet. Wie kommt es dann, dass bei der Funktion "cpu_get_regs" nur ein NOP eingefügt wird. Müsste der Linker hier nicht zwei NOP's einfügen? Ohne zweites NOP zähle ich nämlich 23 Bytes an Code. Die Funktion danach (cpu_port_out8) beginnt deswegen auch an einer ungeraden Adresse (0x00100075).

Auszug aus Anhang dump.txt (siehe oben):
Code:
0010005e <cpu_get_regs>:
  10005e:    55                       push   %ebp
  10005f:    89 e5                    mov    %esp,%ebp
  100061:    83 ec 08                 sub    $0x8,%esp
  100064:    83 ec 0c                 sub    $0xc,%esp
  100067:    ff 75 08                 pushl  0x8(%ebp)
  10006a:    e8 b7 ff ff ff           call   100026 <_cpu_regs_get>
  10006f:    83 c4 10                 add    $0x10,%esp
  100072:    90                       nop
  100073:    c9                       leave 
  100074:    c3                       ret   

00100075 <cpu_port_out8>:
  100075:    55                       push   %ebp
  100076:    89 e5                    mov    %esp,%ebp
  100078:    83 ec 18                 sub    $0x18,%esp
  10007b:    8b 55 08                 mov    0x8(%ebp),%edx
  10007e:    8b 45 0c                 mov    0xc(%ebp),%eax
  100081:    66 89 55 f4              mov    %dx,-0xc(%ebp)
  100085:    88 45 f0                 mov    %al,-0x10(%ebp)
  100088:    0f b6 55 f0              movzbl -0x10(%ebp),%edx
  10008c:    0f b7 45 f4              movzwl -0xc(%ebp),%eax
  100090:    83 ec 08                 sub    $0x8,%esp
  100093:    52                       push   %edx
  100094:    50                       push   %eax
  100095:    e8 72 ff ff ff           call   10000c <_cpu_out_uint8>
  10009a:    83 c4 10                 add    $0x10,%esp
  10009d:    90                       nop
  10009e:    c9                       leave 
  10009f:    c3                       ret
 
Also ich habe mal die man-page von GNU LD durchgelesen. Habe aber nicht das gleiche Flag oder ein ähnliches Flag wie -fno-align-functions gefunden. Ist nur beim GCC bei Optimierungen vermerkt.

Bist du dir sicher, dass der Linker die NOP's einfügt?
 
Interessanter Artikel zwecks Code Alignment auf Stackoveflow.
Für alle die den Link nicht folgen...

Zitat aus dem Intel's Optimization Manual:
3.4.1.5
Code Alignment
Careful arrangement of code can enhance cache and memory locality. Likely sequences of basic blocks
should be laid out contiguously in memory. This may involve removing unlikely code, such as code to
handle error conditions, from the sequence. See Section 3.7, “Prefetching,” on optimizing the instruction
prefetcher.
3-8
GENERAL OPTIMIZATION GUIDELINES
Assembly/Compiler Coding Rule 12. (M impact, H generality) All branch targets should be 16-
byte aligned.
Assembly/Compiler Coding Rule 13. (M impact, H generality) If the body of a conditional is not
likely to be executed, it should be placed in another part of the program. If it is highly unlikely to be
executed and code locality is an issue, it should be placed on a different code page.

Hhm...steht nur was von Verzweigungen (BRANCH bzw. JMP's). Dürfte anscheinend egal sein wenn die CALL's nicht ausgerichtet sind. So verstehe ich es jedenfalls. Sollte ich nicht richtig liegen, dann korrigiert mich bitte.
 
Zurück
Oben