Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can't write to stdout in assembly

11 views
Skip to first unread message

Thomas M. Sommers

unread,
Mar 4, 2000, 3:00:00 AM3/4/00
to freebsd...@freebsd.org
From what I understand, the following should print "Hello, world." on
stdout. I stole the code from the Linux HOWTO, but I think it should
work on FreeBSD as well. Instead, the call to write returns 9 (EBADF).

.data
msg: .string "Hello, world.\n"
len = . - msg - 1
.text
global _start
_start:
movl $4, %eax
movl $1, %ebx
movl $msg, %ecx
movl $len, %edx
int $0x80

movl $1, %eax
xorl %ebx, %ebx
int $0x80

Can anyone explain what I've done wrong?

As a related question, can anyone point me to the source for the int
0x80 handler? I've looked all over but can't find it.

Thanks.


To Unsubscribe: send mail to majo...@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message

Brian Fundakowski Feldman

unread,
Mar 4, 2000, 3:00:00 AM3/4/00
to Thomas M. Sommers
On Sat, 4 Mar 2000, Thomas M. Sommers wrote:

> >From what I understand, the following should print "Hello, world." on
> stdout. I stole the code from the Linux HOWTO, but I think it should
> work on FreeBSD as well. Instead, the call to write returns 9 (EBADF).
>

[ Linux-specific asm elided ... ]


>
> Can anyone explain what I've done wrong?
>
> As a related question, can anyone point me to the source for the int
> 0x80 handler? I've looked all over but can't find it.

You're trying to run Linux assembly on FreeBSD. The calling conventions
are not the same at all, and cannot be treated as such. Even if you
really needed to write in assembly, you shouldn't call the syscalls
directly. Note that the library stubs are just that, stubs to call
the system calls. Try doing something more along the lines of:

pushl $stringlen
pushl stringaddr
pushl $0x1
call write

which would result in %eax containing the return value.

For what it's worth, you can find all of the syscall calling conventions
in src/lib/libc, and you can find where the calling conventions are
"defined" by looking at src/sys/i386/i386/trap.c.

> Thanks.

--
Brian Fundakowski Feldman \ FreeBSD: The Power to Serve! /
gr...@FreeBSD.org `------------------------------'

Thomas M. Sommers

unread,
Mar 5, 2000, 3:00:00 AM3/5/00
to freebsd...@freebsd.org
Marco van de Voort wrote:
>
> > >From what I understand, the following should print "Hello, world." on
> > stdout. I stole the code from the Linux HOWTO, but I think it should
> > work on FreeBSD as well. Instead, the call to write returns 9 (EBADF).
>
> I disassembled FreeBSD programs (create a small C prog, compile, and use
> objdump), and it looks more like this: (I haven't tested this yet, but it is definitely
> stack based, not register based, the part which I haven't tested is if the placing
> the int $0x80 behind a call is required)
>

It turns out that placing the int $0x80 behind a call is required. I
infer that
the kernel does not look for the arguments at the top of the stack, but
farther
down. When you think about it, that makes some sense, since any sane
person would
call the kernel through libc, and not directly. Thanks for the help.

In the remote chance that anyone is interested, here is the code that
works:

.data
msg: .string "Hello, world.\n"
len = . - msg - 1
.text

.global _start
_start:
pushl $len
pushl $msg
pushl $1
movl $4, %eax
call make_syscall
addl $12, %esp

movl $1, %eax
pushl $0
call make_syscall

make_syscall:
int $0x80
ret

Thomas M. Sommers

unread,
Mar 5, 2000, 3:00:00 AM3/5/00
to freebsd...@freebsd.org
Brian Fundakowski Feldman wrote:

>
> On Sat, 4 Mar 2000, Thomas M. Sommers wrote:
>
> > >From what I understand, the following should print "Hello, world." on
> > stdout. I stole the code from the Linux HOWTO, but I think it should
> > work on FreeBSD as well. Instead, the call to write returns 9 (EBADF).
> >
> [ Linux-specific asm elided ... ]
> >
> > Can anyone explain what I've done wrong?
> >
> > As a related question, can anyone point me to the source for the int
> > 0x80 handler? I've looked all over but can't find it.
>
> You're trying to run Linux assembly on FreeBSD. The calling conventions
> are not the same at all, and cannot be treated as such.

I couldn't find any documentation for FreeBSD, so used what I found for
Linux as a first approximation. At least it assembled and ran, even if
it didn't work.

> Even if you
> really needed to write in assembly, you shouldn't call the syscalls
> directly.

I'm doing this as a learning exercise, so I wanted to do it the hard way
first.

> Note that the library stubs are just that, stubs to call
> the system calls. Try doing something more along the lines of:
>
> pushl $stringlen
> pushl stringaddr
> pushl $0x1
> call write
>
> which would result in %eax containing the return value.

Using write, and making the other appropriate changes to the code,
works. write() uses
leal 4, %eax
instead of
movl $4, %eax
before the int $0x80 call. But doing this myself still does not work. At
first glance, it doesn't seem that the C startup stuff does anything
that would affect syscalls, so I don't see why calling write() would
make a difference.

> For what it's worth, you can find all of the syscall calling conventions
> in src/lib/libc, and you can find where the calling conventions are
> "defined" by looking at src/sys/i386/i386/trap.c.

It looks like syscall() in trap.c is where int $0x80 is handled. I'll
have to do some more digging. Thanks for the help.

Marco van de Voort

unread,
Mar 5, 2000, 3:00:00 AM3/5/00
to Hac...@freebsd.org
> >From what I understand, the following should print "Hello, world." on
> stdout. I stole the code from the Linux HOWTO, but I think it should
> work on FreeBSD as well. Instead, the call to write returns 9 (EBADF).

I disassembled FreeBSD programs (create a small C prog, compile, and use


objdump), and it looks more like this: (I haven't tested this yet, but it is definitely
stack based, not register based, the part which I haven't tested is if the placing
the int $0x80 behind a call is required)

pusl $len
pushl $Msg
pushl $1
mov $4,%eax
call _basicsyscall
addl $12,%esp
.
.
.

_basicsyscall: int $0x80
ret


> As a related question, can anyone point me to the source for the int
> 0x80 handler? I've looked all over but can't find it.

On the libc side?

It is very fragmented in several files using a lot of macro
code. If you wish I can look up the names for you (I did this some weeks ago)

I never searched for the kernel side. (the actual 0x80 handler)
Marco van de Voort (Mar...@Stack.nl)
<http://www.stack.nl/~marcov/xtdlib.htm>

0 new messages