syscall Versuch

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 7164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

syscall Versuch

Beitrag von Mathias »

Ich wollte mal syscall ausprobieren. Bei der Zeit abfrage kommt etwas rein.
Aber wieso funktioniert Print nicht ?
Einer eine Idee ?

Code: Alles auswählen

program project1;

type
  TTimeVal = record
    tv_sec: int64;
    tv_usec: int64;
  end;
  PTimeVal = ^TTimeVal;

  // /usr/include/x86_64-linux-gnu/asm/unistd_64.h

  {$asmmode intel}

  function ManualGetTimeOfDay(tv: PTimeVal): int64; assembler; nostackframe;
  asm
           Mov     Rax, 96
           Mov     Rdi, tv
           Xor     Rsi, Rsi
           Syscall
  end;


  function Print(c: pchar; len: int64): int64; assembler; nostackframe;
  asm
           Mov     Rax, 1
           Mov     Rdi, 1
           Mov     Rsi, c
           Mov     Rdx, len
           Syscall
  end;


  procedure main;
  var
    start, ende: TTimeVal;
    c: double;
    i: integer;
  var
    demo: pchar = 'syscall demo'#10;
  begin
    Print(demo, Length(demo));

    ManualGetTimeOfDay(@start);

    for i := 0 to 1000000 do begin
      c := cos(c);
    end;

    ManualGetTimeOfDay(@ende);

    WriteLn('Rechenzeit: ', ende.tv_usec - start.tv_usec);
  end;

begin
  main;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 1020
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: syscall Versuch

Beitrag von PascalDragon »

Mathias hat geschrieben: Sa 27. Dez 2025, 15:34

Code: Alles auswählen

  function Print(c: pchar; len: int64): int64; assembler; nostackframe;
  asm
           Mov     Rax, 1
           Mov     Rdi, 1
           Mov     Rsi, c
           Mov     Rdx, len
           Syscall
  end;
Du musst aufpassen, da du dir hier deine Argumente überschreibst. Der finale Assembly Code ist dies:

Code: Alles auswählen

section .text.n_p$project1_$$_print$pchar$int64$$int64
        .balign 16,0x90
.globl  P$PROJECT1_$$_PRINT$PCHAR$INT64$$INT64
        .type   P$PROJECT1_$$_PRINT$PCHAR$INT64$$INT64,@function
P$PROJECT1_$$_PRINT$PCHAR$INT64$$INT64:
.Lc3:
# [24] asm
#  CPU ATHLON64
# [25] Mov     Rax, 1
        movq    $1,%rax
# [26] Mov     Rdi, 1
        movq    $1,%rdi
# [27] Mov     Rsi, c
        movq    %rdi,%rsi
# [28] Mov     Rdx, len
        movq    %rsi,%rdx
# [29] Syscall
        syscall
#  CPU ATHLON64
# [30] end;
        ret
.Lc4:
.Le1:
        .size   P$PROJECT1_$$_PRINT$PCHAR$INT64$$INT64, .Le1 - P$PROJECT1_$$_PRINT$PCHAR$INT64$$INT64
Der SysCall Code in FPCs RTL hat je eine Funktion in Assembly für die verschiedenen Anzahlen an Parametern, die es gibt und ruft diese dann entsprechend aus den eigentlichen Funktionen auf, so dass in den SysCall Funktionen selbst nicht so sehr mit den Parametern jongliert werden muss, sondern stattdessen der Compiler dies beim Aufruf macht.

Weiterer Tipp, wenn du mit SysCalls arbeitest: schau dir das Tool strace an. Das gibt alle SysCalls aus, die dein Programm macht inklusive Argumente. ;)
FPC Compiler Entwickler

Mathias
Beiträge: 7164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: syscall Versuch

Beitrag von Mathias »

Jetzt ist der Fall klar, ich habe Register überschrieben. So geht es: `

Code: Alles auswählen

  function Print(c: pchar; len: int64): int64; assembler; nostackframe;
  asm
           Mov     Rax, 1
           Mov     Rdx, len
           Mov     Rsi, c
           Mov     Rdi, 1
           Syscall
  end;    
Weiterer Tipp, wenn du mit SysCalls arbeitest: schau dir das Tool strace an. Das gibt alle SysCalls aus, die dein Programm macht inklusive Argumente. ;)
Das sieht man gut, das das WriteLn intern auch einen syscall macht.

Code: Alles auswählen

strace ./project1
execve("./project1", ["./project1"], 0x7ffdeb817420 /* 49 vars */) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
rt_sigaction(SIGFPE, {sa_handler=0x425cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x401300}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGSEGV, {sa_handler=0x425cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x401300}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGBUS, {sa_handler=0x425cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x401300}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGILL, {sa_handler=0x425cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x401300}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x4), ...}) = 0
fstat(2, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x4), ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x4), ...}) = 0
fstat(2, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x4), ...}) = 0
write(1, "syscall demo\n", 13syscall demo
)          = 13
gettimeofday({tv_sec=1766906761, tv_usec=238926}, NULL) = 0
gettimeofday({tv_sec=1766906761, tv_usec=284019}, NULL) = 0
write(1, "Rechenzeit: 45093\n", 18Rechenzeit: 45093
)     = 18
exit_group(0)                           = ?
+++ exited with 0 +++
So nebenbei habe ich jetzt den lästigen float point Fehler gefunden, welcher bei C Bindungen auftreten kann., FPC überschreibt knallhart dieses signal.

Code: Alles auswählen

rt_sigaction(SIGFPE, {sa_handler=0x425cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x401300}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 1020
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: syscall Versuch

Beitrag von PascalDragon »

Mathias hat geschrieben: So 28. Dez 2025, 08:27 So nebenbei habe ich jetzt den lästigen float point Fehler gefunden, welcher bei C Bindungen auftreten kann., FPC überschreibt knallhart dieses signal.

Code: Alles auswählen

rt_sigaction(SIGFPE, {sa_handler=0x425cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x401300}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
Natürlich macht FPC das, da die RTL Fließkommaausnahmen behandeln können muss.
FPC Compiler Entwickler

Antworten