Einzelnen Beitrag anzeigen

Benutzerbild von mael
mael

Registriert seit: 13. Jan 2005
391 Beiträge
 
Delphi XE3 Professional
 
#8

AW: Delphi -> Assembler -> Interrupt

  Alt 12. Jul 2017, 17:45
procedure TForm1.Maus_an;
asm
mov ax, 01h
int 33h
end;
Bei Assembler denkt man immer man wäre näher an der Hardware, aber der Interrupt ist auch nur ein Funktionsaufruf der unter DOS an den Maustreiber weitergleitet wird.

Siehe z.B. hier: http://stanislavs.org/helppc/int_33-0.html
Zitat:
on return:
AX = 0000 mouse driver not installed
FFFF mouse driver installed
Unter DOS wurden Systemfunktionen durch Interrupts aufgerufen, weil es die einzige Möglichkeit ist bei singlethreaded Anwendungen die Kontrolle abzugeben. Unter Win3.1 wurde dafür kooperatives Multitasking verwendet. Man muss hier regelmäßig prüfen ob es neue Fensterbotschaften gibt und diese verarbeiten oder Yield aufrufen um dem Betriebssystem zeitweilig die Kontrolle zurückzugeben.

Unter Windows erreicht man Effizienz durch Verwendung von DirectX oder OpenGL oder ähnliche APIs oder spezielle Sound-APIs die niedrige Latenz ermöglichen, wie ASIO oder WASAPI, etc.

Assembler ist nicht an sich schneller oder näher an der Hardware. Compiler erzeugen auch Maschinencode, nur manchmal ist er suboptimal. Wenn es darum geht eine API-Funktion oder Interrupt aufzurufen ist es eher unwahrscheinlich dass beim Aufruf groß Latenz dazukommt.

Allerdings kannst du Windows-APIs (oder andere C-APIs wie sie heute üblich sind) auch per Assembler aufrufen. Dafür musst du nur die Calling-Convention kennen.

Ich habe hier mal ein einfaches Beispiel für GetCursorPos gemacht:
Code:
procedure Success;
begin
  ShowMessage('Success');
end;

procedure Fail;
begin
  ShowMessage('Fail');
end;

procedure DoSomethingInAssembler;
var
  p: TPoint;
asm
  // load address of p in eax and push it onto the stack
  lea eax, [p]
  push eax

  // GetCursorPos expects its TPoint parameter to be on the stack (stdcall convention)
  call GetCursorPos
  // boolean result returned in eax
  cmp eax,0

  // jump to fail if eax=0
  je @@fail

  // show message 'success' if eax=1
  call Success
  jmp @@exit

@@fail:
  call Fail

@@exit:
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DoSomethingInAssembler;
end;
Wenn man statt "lea eax, [p]" "mov eax, 0" schreibt, wird er "Fail" ausgeben, weil man nun einen Null-Pointer übergeben hat. Der Code funktioniert nur für 32-Bit Windows, die calling convention unter Win64 ist anders.

Das nur als kleines Beispiel. Falls noch nicht bekannt, Strg+Alt+C zeigt das CPU-Fenster (während dem Debuggen), wo man die Assembler-Instruktionen sehen kann, die dem Pascal-Code entsprechen.

Assembler ist wirklich nur selten sinnvoll heutzutage, um den Compiler zu überzeugen einige umständliche Konstrukte zu vermeiden, oder ungewöhnliche calling conventions zu unterstützen oder sonstige Hacks. In seltenen Fällen um SIMD-Instruktionen zu verwenden, falls der Compiler sie nicht unterstützt. Aber auch da gibt es normalerweise bessere Lösungen wie z.B. OpenCL.
HxD, schneller Hexeditor:
http://mh-nexus.de/hxd

Geändert von mael (12. Jul 2017 um 17:55 Uhr)
  Mit Zitat antworten Zitat