0

I learned assembly starting at x64 architecture, now I'm a bit confused about x86 architecture.

When looking at x86 syscall tables on the internet, the arguments for the syscalls are (just like x64) to be put in various registers.

E.g. the argument "Exit Code" for "sysexit" should be put into ebx.

global _start
section .text
_start:
   mov  ebx, 42
   mov  eax, 1
   int  0x80

echo $?
42

That works fine.

However I follow an online course where they keep putting syscall arguments onto the stack.

global _start
section .text
_start:
   mov  eax, 1
   push 42
   int  0x80

echo $?
0

That doesn't work for me.

I also tried several assemblers (nasm, gcc), tried to put esp into ebx (cause I've seen that in other 32bit assembly code, after they pushed the arguments onto the stack they saved the stack pointer into ebx) - when I did that I got "44" as exit code, weirdly.

Then I went searching and found there several different calling convetions, CDECL, FASTCALL, etc.. this is pretty confusing tbh.

How can I get 32bit sysexit work in assembly while pushing it's argument onto the stack?

Lee.D
  • 1
  • 2
  • 2
    Is the online course perhaps not for Linux? Maybe you have a link? The `exit` system call on Linux requires its argument in `ebx`. It cannot be passed through the stack. – fuz Feb 12 '22 at 13:51
  • Linux vs. Windows. These are calling conventions for software interrupts. –  Feb 12 '22 at 13:54
  • The course is for both Windows and Linux, but this was from the linux section. So in x86 Linux we don't push arguments to the stack? Is this true only for syscalls or also for regular function calls? BTW: It's INE Exploit Developer course, you can look it up yourself. Maybe the author confused it, the whole material seems very dated. – Lee.D Feb 12 '22 at 13:59
  • x86 Linux does not look for system-call args on the user-space stack, only in up-to-6 registers. *BSD does use the user-space stack, but the first arg is at `ESP+4`. (So their libc system-call wrapper functions can just mov to EAX and `int`, with the return address taking up the unused space.) If any course material is telling you to `push` / `int 0x80`, it's either wrong or not for Linux. See [What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64](https://stackoverflow.com/q/2535989) – Peter Cordes Feb 12 '22 at 17:36
  • 32-bit Linux *function* calls do pass args on the stack; it uses the i386 System V ABI. (Also you can look at compiler output for function calls, unlike raw system calls: https://godbolt.org/) – Peter Cordes Feb 12 '22 at 18:47
  • @PeterCordes don't you want to work your comment into an answer, including a tiny demo (function can be very simply with only one arg)? – Lee.D Feb 12 '22 at 19:34
  • Not really; all of this has been explained multiple times before on Stack Overflow. I could add another duplicate link if you want one about passing args to functions that you `call` rather than raw system-calls. This question doesn't mention the name of any specific tutorial or other wrong resource that would let future readers also misled by it find this question more easily, so it seems to me just an obvious duplicate of the canonical Q&A about system-call vs. function-call calling conventions. – Peter Cordes Feb 12 '22 at 19:39

0 Answers0