0

There are countless questions regarding GCC extended ASM, but none seemed to be able to remedy my problem. I am trying to write a simple block of code that triggers a syscall to open. I have come up with the following:

int fd;
char file[] = "/path/to/file";
asm volatile ("int $0x80"
               : "=a"(fd) 
               : "0"(__SYS_open), "D"(file), "S"(O_RDONLY)
               : "cc","%edi","%esi");

Attempting to compile code containing the above asm reference leads to:

error: ‘asm’ operand has impossible constraints

I noticed that removing "%edi","%esi" from the clobber list allows the code to compile without error. I am able to include registers in the clobber list that I do not explicitly request in the constraints (e.g. ecx), so perhaps I am misunderstanding the clobber list.

The binary this code will be executed from is x86_64.

old_timer
  • 69,149
  • 8
  • 89
  • 168
sherrellbc
  • 4,650
  • 9
  • 48
  • 77
  • Certain versions of gcc don't allow clobbering input operands. You have to declare them as dummy outputs. Anyway, the syscall does not clobber `edi` or `esi`, so really no reason to list them. Also, if you are using 64 bit, you should use `syscall` instruction (with the changed ABI), not `int 0x80`. PS: obviously you should have a really good reason to use this instead of just `open()`. – Jester Sep 15 '17 at 14:04
  • Any reason you don't use GCC's [syscall](https://www.gnu.org/software/libc/manual/html_node/System-Calls.html) function – Michael Petch Sep 15 '17 at 14:16
  • 1
    @Jester: There's a canonical Q&A about (not) using `int 0x80` in 64-bit code: https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit-int-0x80-linux-abi-in-64-bit-code. – Peter Cordes Sep 15 '17 at 14:17
  • 1
    Clobbers are for registers you destroy but that don't hold input or output operands. (And you're not allowed to destroy input operands unless there's an output operand using the same register.) – Peter Cordes Sep 15 '17 at 14:19
  • If you includes `asm/unistd.h`, this will call the wrong system call when you run it; see https://stackoverflow.com/questions/2500362/running-32-bit-assembly-code-on-a-64-bit-linux-64-bit-processor-explain-the. Only the call numbers from `asm/unistd_32.h` work with `int 0x80` on Linux. – Peter Cordes Sep 15 '17 at 14:21
  • 1
    Inline assembly should be used as a last resort. Don't use inline assembly if you don't have to. Even the simplest of assembly templates can be problematic. You need to use `syscall` instead of `int $0x80` (you seem to have mixed the 32-bit and 64-bit calling conventions. Assuming you did mean to create 64-bit code this should work `asm volatile ("syscall" : "=a"(fd) : "0"(SYS_open), "D"(file), "S"(O_RDONLY), "m"(*(const struct {char x; char y[];} *) file) : "cc", "rcx", "r11");` . _RCX_ and _R11_ get clobbered by syscall as well as RAX – Michael Petch Sep 15 '17 at 15:27
  • The extra memory constraint is required to insure that the string associated with `file` is properly stored to memory before the assembly template is invoked. Without that fake memory constraint It is possible with optimizations on and code structured a certain way to not have the string `file` fully realized in memory before the `asm` code is executed. This would lead to the wrong file name being opened. – Michael Petch Sep 15 '17 at 15:32
  • Possible duplicate of [How do I tell GCC asm that an input register is clobbered?](https://stackoverflow.com/questions/26942064/how-do-i-tell-gcc-asm-that-an-input-register-is-clobbered). Regardless of the OP trying to do the wrong thing with inline-asm, the actual question (about clobbers on operands) is a duplicate this, not any of the system-call stuff. – Peter Cordes Sep 16 '17 at 05:30

0 Answers0