9

Since MS‑DOS, I know system invocation using interrupts. In old papers, I saw reference to int 80h to invoke system functions on Linux. Since a rather long time now, I know int 80h is deprecated in favour of the syscall instruction. But I can't get it working on my 32 bits machine.

The question

Is the syscall instruction to be used on 64 bits platform only? Doesn't 32 bits Linux makes use of syscall?

A sample test

On my 32 bits Linux (Ubuntu Precise), this program terminates with a core dump:

global _start

_start:
        mov     eax, 4                ; 4 is write
        mov     ebx, 1                ; 1 is stdout
        mov     ecx, message          ; address of string
        mov     edx, length           ; number of bytes
        syscall

        mov     eax, 1                ; 1 is exit
        xor     ebx, ebx              ; return code 0
        syscall

message:
        db  10,"Hello, World",10,10
length  equ $ - message

I've tried with sysenter instead of syscall, but it crashes the same way.

Hibou57
  • 6,870
  • 6
  • 52
  • 56
  • possible duplicate of [What is better "int 0x80" or "syscall"?](http://stackoverflow.com/questions/12806584/what-is-better-int-0x80-or-syscall) – Michael Mar 24 '13 at 13:11
  • 1
    There is indeed something related, [here](http://stackoverflow.com/a/12806910/279335), but which does not answer the question. He says `syscall` isn't available in 32 bits mode of Intel CPUs, but the assembler compiled it in 32 bits mode; either the assertion is unclear or it is wrong. Then, I get a core‑dump due to an illegal instruction, but this instruction is available on all Intel CPU starting with Pentium II, and mine is far above that. He mention `sysenter`, which I tried with the same result. Anyway, I've never seen any mention of `sysenter` in Linux ABI, only `int 80h` or `syscall`. – Hibou57 Mar 24 '13 at 13:59
  • 2
    Well, according to “[System Calls (wiki.osdev.org)](http://wiki.osdev.org/System_Calls)”, `syscall` is the AMD equivalent of the Intel `sysenter`. It says “*On Intel CPU, starting from the Pentium II, a new instruction pair sysenter/sysexit has appeared. It allows a faster switch from user mode to kernel mode, by limiting the overhead of changing mode. **A similar instruction pair has been created by AMD: Syscall/Sysret**. However the behaviour of these instructions are different from Intel's.*” – Hibou57 Mar 24 '13 at 14:10
  • 2
    For reference, int 0x80 has always been a Linux thing. Windows and MS-DOS used int 0x2E – SecurityMatt Mar 25 '13 at 16:39
  • 1
    The recommendation to choose one over the other is for OS kernel developers. Their choice is then made part of the ABI, and if you are developing for a certain OS, you must honour that ABI. For example, Linux/i386 uses int 0x80 and passes arguments in registers, whereas MirBSD/i386 uses int 0x80 and passes arguments on the stack, with one frame pointer in between (which means no setup cost in userspace when using cdecl). – mirabilos Dec 06 '13 at 21:08

2 Answers2

6

After some web searching, I landed to this other topic on StackOverflow: Linux invoke a system call via sysenter tutorial. It says the recommended way to invoke the system, is neither using int 80h nor syscall nor sysenter, but linux-gate.so.

Still remains the question about the crash and core‑dump. My guess is finally that although either syscall or sysenter instructions are available as a CPU instruction, may be the Linux kernel just does not set‑up properly this “entry point” when it decide it's not really useful on a given hardware platform.

Seems on 32 bits platform, sysenter or syscall may be available, while it's always available, only on 64 bits platform.

Although I feel this answer my question, I still welcome more material, like an authoritative reference for my above guess.

-- update --

At least, I could find this which confirm the above. That's still not an authoritative reference but seems trustable enough I believe.

What is linux-gate.so.1?, says:

The preferred way of invoking a system call is determined by the kernel at boot time, and evidently this box uses sysenter.

Also, from another source, a sample FASM assembly source (needs some translations if you use NASM), to call a system function via linux-gate.so: Finding linux-gate.so.1 in Assembly .

Community
  • 1
  • 1
Hibou57
  • 6,870
  • 6
  • 52
  • 56
  • 1
    Note that when using sysenter/syscall, the convention might not entierly the same as for using int 0x80. For `sysenter` you'll need, iirc, `push ecx push edx push ebp mov ebp,esp` right before the `sysenter` – nos Dec 08 '13 at 13:26
  • 1
    Note that since it's `determined by the kernel at boot time` you get int 80, sysenter or syscall depending on the capabilities of the CPU. Int 80 will always work but is slow and on newer CPUs only one of sysenter or syscall works. It's not a choice the program should make, the kernel makes the optimal choice for you. – Goswin von Brederlow Jul 07 '16 at 17:12
6

The Intel manual says that syscall is invalid in compatibility (32-bit) mode, so it should not be used by the kernel.

This seems to be an Intel-only restriction however: https://stackoverflow.com/a/29784932/895245 that AMD does not have, but certainly Linux has to support Intel :-)

sysenter appears to be the best way to do it today as it is faster than int 0x80, but it should be used indirectly through VDSO as explained at How to invoke a system call via sysenter in inline assembly (x86/amd64 linux)?

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • 1
    Someone raised the same as a comment on the initial question. I answered the instruction is compiled by the assembler I used without even a warning and the opcode was documented for 32 bits. May be this is invalid in 32 bits mode of 64 bits architecture only… Anyway, as you said, in the context of Linux, it's better to rely on the VDSO (there are methods to retrieve it even without Glibc). – Hibou57 Apr 22 '15 at 17:06
  • 1
    @Hibou57: As per [this comment thread](http://stackoverflow.com/questions/38063529/x86-32-x86-64-polyglot-machine-code-fragment-that-detects-64bit-mode-at-run-ti/38063530?noredirect=1#comment63566180_38063530): it's valid in 32bit mode on AMD CPUs only. I was surprised too that it assembles and disassembles in 32bit code, but apparently AMD introduced syscall separately from (and maybe before) the AMD64 architecture. Intel's instruction won for 32bit mode (as usual), but AMD's became the standard for AMD64. – Peter Cordes Jun 27 '16 at 21:56