Timeline for Tips for golfing in x86/x64 machine code
Current License: CC BY-SA 4.0
24 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Feb 12, 2023 at 17:28 | comment | added | Peter Cordes | @qwr: None of the answers I linked about register state are about functions, only _start. If anything else has run before in user-space, you can't assume any register values except what the ABI guarantees. In Linux _start, [esp] is argc; the stack pointer points at argc then argv. So you can pop it into another register (a one byte instruction), but esp itself is a pointer, not small-integer argc. | |
| Feb 12, 2023 at 16:46 | comment | added | qwr | Some of this answer is for functions. What do you think about "full programs", those that start at _start and then exit if not looping forever? In my cat program, I clobbered esp since I think it actually has argc on startup | |
| Feb 11, 2023 at 0:35 | comment | added | Peter Cordes | @qwr: my comment on another answer on this question already said that; I edited it into that answer to summarize the link to Linux startup state details. | |
| Feb 11, 2023 at 0:06 | comment | added | qwr | @PeterCordes can you put that as an answer here? because that would save bytes for programs that start at _start | |
| Feb 10, 2023 at 23:51 | comment | added | Peter Cordes | @qwr: It's usable in code-golf because it's true in practice in a static executable under Linux. It's not guaranteed by any ABI docs, it's just what Linux chooses to do to avoid info leaks since version 2.2.0: What is the default register state when program launches (asm, linux)?. In dynamically-linked executables where other code runs before your _start, registers won't be zeroed. | |
| Feb 10, 2023 at 23:11 | comment | added | qwr | Is it reasonable to assume a bunch of registers will be zero'd on program entry? I can't find where this is documented for 32-bit x86 linux programs but all the registers except for rsp and rip are zero'd when I break at _start but not for main in gdb. | |
| Mar 23, 2022 at 18:04 | comment | added | Peter Cordes | @l4m2: I guess you could do that; requiring an 8-bit arg to be zero-extended to a full register is not that weird, in fact clang will make code that assumes that for int foo(uint8_t x){ return x; } godbolt.org/z/dqM7783Ez as an undocumented extension to the x86-64 SysV calling convention which GCC follows when calling but doesn't assume in callees. Or just say the arg is an int, like ISO C isalpha takes. | |
| Mar 23, 2022 at 12:47 | comment | added | l4m2 | Is it ever used that take a byte in eax and use the free zero ah? | |
| Apr 29, 2021 at 4:53 | comment | added | Peter Cordes | typo in previous comment: "of different type may matter", for compilers reusing arg-passing stack space for different args as a tailcall. | |
| S Feb 18, 2021 at 2:10 | history | edited | Peter Cordes | CC BY-SA 4.0 | Not every mention of a register has to be code; that dilutes the impact of actual code and looks visually messy in some cases. call/ret are also English words for the act of calling. |
| S Feb 18, 2021 at 2:10 | history | suggested | EasyasPi | CC BY-SA 4.0 | Slight grammar fixes, improve consistency in formatting |
| Feb 18, 2021 at 1:42 | review | Suggested edits | |||
| S Feb 18, 2021 at 2:10 | |||||
| Feb 17, 2021 at 11:29 | history | edited | Peter Cordes | CC BY-SA 4.0 | wrong link for chromakey answer. |
| Jun 17, 2020 at 9:04 | history | edited | CommunityBot | Commonmark migration | |
| May 5, 2019 at 6:50 | comment | added | Peter Cordes | @dfeuer Yes. jmp instead of call / ret is only possible if the number of stack args for the target function is less than or equal to the stack arg space for this function. (Or for callee-pops with ret 12 for example, if it matches exactly). Many compilers have missed optimizations about re-using their own stack-arg space for tailcall args (of different may matter). godbolt.org/z/Nty30a. So register-arg calling conventions help a lot, both to avoid missed optimations, and to make tailcalls possible when the target has more args than this function. | |
| May 5, 2019 at 6:31 | comment | added | dfeuer | Do language implements with full tail-call optimization all preserve ESP/RSP? | |
| May 3, 2019 at 21:00 | history | edited | Peter Cordes | CC BY-SA 4.0 | oops, args reversed for LEA, maybe I was thinking in AT&T syntax. |
| Mar 12, 2019 at 19:01 | comment | added | user58988 | It is possible return one array if 1) that array is given in the arguments or 2) use malloc() and who call has the responsibility of free that array with free() function | |
| Mar 12, 2019 at 18:56 | comment | added | user58988 | Call push the address of instruction after the call in the stack jmp to function called; ret pop the address from the stack and jmp to that address | |
| May 18, 2018 at 23:56 | comment | added | Peter Cordes | @qwr: x86 isn't a "stack based language". x86 is a register machine with RAM, not a stack machine. A stack machine is like reverse-polish notation, like x87 registers. fld / fld / faddp. x86's call-stack doesn't fit that model: all normal calling conventions leave RSP unmodified, or pop the args with ret 16; they don't pop the return address, push an array, then push rcx / ret. The caller would have to know the array size or have saved RSP somewhere outside the stack to find itself. | |
| May 18, 2018 at 23:37 | comment | added | qwr | so what do you think about reasonable or not? Do you count x86 under this rule codegolf.meta.stackexchange.com/a/8507/17360 | |
| May 18, 2018 at 20:14 | comment | added | Peter Cordes | @qwr: no, the mainstream calling conventions pass a hidden pointer to the return value. (Some conventions pass/return small structs in registers). C/C++ returning struct by value under the hood, and see the end of How do objects work in x86 at the assembly level?. Note that passing arrays (inside structs) does copy them onto the stack for x86-64 SysV: What kind of C11 data type is an array according to the AMD64 ABI, but Windows x64 passes a non-const pointer. | |
| May 18, 2018 at 18:52 | comment | added | qwr | When challenges ask to return an array, do you think returning on the stack is reasonable? I think that's what compilers will do when returning a struct by value. | |
| May 18, 2018 at 5:03 | history | answered | Peter Cordes | CC BY-SA 4.0 |