Skip to main content
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