Author Topic: Push extra long in non-NASM examples  (Read 11931 times)

Offline MrCBofBCinTX

  • Jr. Member
  • *
  • Posts: 18
    • Capuchado!
Push extra long in non-NASM examples
« on: October 24, 2012, 10:19:02 AM »
I keep seeing other examples ( not NASM ) saying that pushing an extra long is needed.
But I don't see that here or any other examples I see.
What's up with this?

Code: [Select]
section .note.openbsd.ident
 align 2
 dd 8
 dd 4
 dd 1
 db 'OpenBSD',0
 dd 0
 align 2

section .text
    global _start ;must be declared for linker (ld)

_syscall:
int 0x80 ;system call
ret

_start: ;tell linker entry point

push dword len ;message length
push dword msg ;message to write
push dword 1 ;file descriptor (stdout)
mov eax,0x4 ;system call number (sys_write)
call _syscall ;call kernel

;the alternate way to call kernel:
;push eax
;call 7:0

add esp,12 ;clean stack (3 arguments * 4)

push dword 0 ;exit code
mov eax,0x1 ;system call number (sys_exit)
call _syscall ;call kernel

;we do not return from sys_exit,
;there's no need to clean stack
section .data

msg db "Hello, world!",0xa ;our dear string
len equ $ - msg ;length of our dear string



This needs an extra long (of any value) pushed.

Code: [Select]
entropy@theo {~/asm} cat hello.s
.section ".note.openbsd.ident", "a"
   .p2align 2
   .long    0x8
   .long    0x4
   .long    0x1
   .ascii "OpenBSD\0"
   .long    0x
   .p2align 2
.section .data
hello:
   .ascii "Hello, World!\n\0"
.section .text
.globl _start
_start:
   pushl $14      # number of bytes to write
   pushl $hello   # address of our string
   pushl $1       # 1 is stdout
   pushl %eax     # push the extra long
   movl $4, %eax  # 4 is write syscall
   int $0x80      # call the kernel
   addl $12, %esp # clean the stack - add ((# of pushl's)-1)*4 to esp
   xor %eax, %eax # set eax to 0
   pushl %eax     # pushl return (status value)
   pushl %eax     # pushl extra long
   movl $1, %eax  # 1 is exit syscall
   int $0x80      # call the kernel
Assemble, link and execute.

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Push extra long in non-NASM examples
« Reply #1 on: October 24, 2012, 01:01:05 PM »
I'm not sure of the exact history but apparently that extra push is needed for all BSDs.  In your first example the extra push is accomplished via the call opcode which pushes the eip on the stack.  Without using call, as in your second example, you must push a value ( it doesn't seem to matter what value you push ).  Thus, from the int 0x80 point of view, the first parameter is always at the same offset on the stack on entry.  Also remember if you push the extra value yourself you need to account for that in stack cleanup too.  In your 2nd example you really need addl $16, esp instead of addl $12, esp

It may make more sense if you think about how the stack is affected via a call using the C calling convention.  This is also one of the differences between Linux and BSD whereby Linux uses registers, rather than the stack, when passing values to the kernel.  For x64 kernel calls: the syscall opcode replaces int 0x80 and both use similar registers for parameters: EDI,ESI,EDX,ECX,R8,R9 ( except Linux uses R10 instead of RCX for any syscall having 4 or more parameters ).

Hope that helps.

Offline MrCBofBCinTX

  • Jr. Member
  • *
  • Posts: 18
    • Capuchado!
Re: Push extra long in non-NASM examples
« Reply #2 on: October 25, 2012, 11:25:25 AM »
Thanks,
I tried with the extra 16 on esp and with int 80h directly. Works fine.