3 ms·
Both are valid, but I much prefer the `register` method I gave (documented in https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html https://gcc.gnu.o
by dundarious 3y ago
Both are valid, but I much prefer the `register` method I gave (documented in https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables....), as it is far more self-explanatory. GCC's extended asm syntax has too many inscrutable constraint and modifier codes even excluding these GCC-ext-asm-specific codes to reference machine-specific registers by name. As such, I totally disagree with your statement about "the only good use". Given that I first learned about that method of specifying registers by reading linux kernel source code, I think others would disagree as well.
- Dwedit 3y agoI think the GCC ASM syntax for specifying inputs and outputs is quite clear enough, and doesn't require a variable declaration with unusual syntax.
- dundarious 3y agoI'm merely referring to the fact that I specified rdi by writing "rdi" not "D". I can specify r10 by writing "r10", but I can't remember how to specify that directly in the inputs/outputs constraints -- a glance at https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html didn't show me how either, but I'm guessing it's there. [Edit: Although, on second glance, from https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Input-Operands https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Input-O...: > If you must use a specific register, but your Machine Constraints do not provide sufficient control to select the specific register you want, local register variables may provide a solution (see Specifying Registers for Local Variables). indicates in the r10 case maybe you _must_ use the syntax I gave?] My preference is for the syntax that requires looking up fewer tables in GCC docs, but as I said, the version you prefer is fine too.
- LegionMammal978 3y agoIndeed, the register variable syntax is necessary for many of the registers; there are only so many of them that have been stuffed into the one-letter constraint. I've used it before for making raw x86-64 Linux syscalls (which can use r10, r8, and r9) without going through errno, as part of a silly little project ([0]) to read from a file descriptor without writing to process memory. [0] https://pastebin.com/mepsedCC https://pastebin.com/mepsedCC
- dundarious 3y agoNice. Yes, linux/tools/include/nolibc has syscall macros that look near identical.
- asveikau 3y agoOne of the reasons for gcc's inline asm syntax being so verbose is it tells the compiler which registers are used and how. There is no indication in your last asm() that the value of rax before the asm() is read from. This means the compiler could assume it's safe to clobber rax just before. After all, you assigned a value into rax and never read it, a reasonable optimizer might say, why emit that first assignment at all?
- dundarious 3y agoI think you should read https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Input-Operands https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Input-O... and the link I gave earlier, if you think my example is something novel of my own construction. It's basically straight from the GCC docs. If your point is that I don't use result, that's because it's a snippet written into Hacker News. I didn't write the code to convert it into an errno and return -1 on error, etc., but doing so would be perfectly valid, and safe from your reasonable optimizer concerns.
- asveikau 3y agoI see absolutely no examples in that link there where they assign into a register via C code, not using it anywhere else, and then assume you can read the same value back from that register in an asm() statement without declaring it as an input.
- dundarious 3y agoI referenced both links (the latter links to the former, and the former, which was in the first comment of mine you replied to, contains the following examples: register int *p1 asm ("r0") = …; register int *p2 asm ("r1") = …; register int *result asm ("r0"); asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2)); and int t1 = …; register int *p1 asm ("r0") = …; register int *p2 asm ("r1") = t1; register int *result asm ("r0"); asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2)); In my example, nr is rax and listed in the input section, rfd is rdi and also listed in the input section, and result is rax and listed in the output section (I even used your preferred syntax for specifying rax here). Using result after the syscall asm statement is perfectly valid.