Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Nov 2009 19:45:10 +0200
From:      Giorgos Keramidas <keramida@ceid.upatras.gr>
To:        David Jackson <norstar39@gmail.com>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: Problems with FreeBSD assembly
Message-ID:  <87fx8jeixl.fsf@kobe.laptop>
In-Reply-To: <4AFB13D9.9050507@gmail.com> (David Jackson's message of "Wed, 11 Nov 2009 14:43:21 -0500")
References:  <4AFB13D9.9050507@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 11 Nov 2009 14:43:21 -0500, David Jackson <norstar39@gmail.com> wrote:
> I am having great difficulty running a very simple assembler program
> on FreeBSD on x86 in my efforts to learn some assembly programming on
> FreeBSD.  I have tried to compile the following with nasm, however i
> get nothing in response when I attempt to run this program:
>
>        section .data
>        hello   db      'Hello, World!', 0xa
>        hbytes  equ     $ - hello
>
>        section .text
>        global  _start
>        _start:
>        push    dword hbytes
>        push    dword hello
>        push    dword 1
>        mov eax,0x4
>        int 0x80
>        add esp,12
>
>        push    dword 0
>        mov eax,0x1
>        int 0x80
>
> nasm -f elf -o hello1s.o hello1.s
> ld -s -o hello1s hello1s.o
>
> ./hello1s prints nothing.
>
> What is wrong here? It should print "hello world".
> Thanks in advance for   your help, it is greatly appreciated.

Hi David.  The truss utility is your friend when you are trying to
decipher system call problems.  It can translate system call arguments
to human-readable output; a very useful property when debugging issues
like this.  For example here's the output for your original code:

    $ truss ./hello
    write(134516904,0xe,1)                           ERR#9 'Bad file descriptor'
    process exit, rval = 1

Note how the arguments of write() are 'misplaced'?  The answer is that
you are not calling the system call with C-like conventions (including a
function call return address).  The calling conventions of system calls
are described in the Developer's Handbook at:

    http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html

You are missing a dword push before interrupting.  As the dev handbook
says, you have to use C calling conventions or push an extra (ignorable)
dword before interrupting:

    An assembly language program can do that as well. For example, we could
    open a file:

    | kernel:
    |     int 80h ; Call kernel
    |     ret
    |
    | open:
    |     push    dword mode
    |     push    dword flags
    |     push    dword path
    |     mov     eax, 5
    |     call    kernel
    |     add     esp, byte 12
    |     ret

    This is a very clean and portable way of coding. If you need to port
    the code to a UNIX system which uses a different interrupt, or a
    different way of passing parameters, all you need to change is the
    kernel procedure.

    But assembly language programmers like to shave off cycles. The
    above example requires a call/ret combination. We can eliminate it
    by pushing an extra dword:

    | open:
    |     push    dword mode
    |     push    dword flags
    |     push    dword path
    |     mov     eax, 5
    |     push    eax              ; Or any other dword
    |     int 80h
    |     add     esp, byte 16

So by pushing *one* more dword before you interrupt should work fine
(and it does, from a small test I ran just now):

: keramida@kobe:/home/keramida$ cat hello.s
:         section .data
: hello   db      'Hello, World!', 0xa
: hbytes  equ     $ - hello
:
: section .text
: global  _start
: _start:
:         push dword hbytes
:         push dword hello
:         push dword 1
:         push dword 0                  ;or any other dword
:         mov eax, 4
:         int 0x80
:         add esp, byte 16
:
:         push dword 0
:         push dword 0                  ;ignored dword
:         mov eax, 1
:         int 0x80
:         add esp, byte 8               ;NOT REACHED
: keramida@kobe:/home/keramida$ nasm -f elf -o hello.o hello.s
: keramida@kobe:/home/keramida$ ld -s -o hello hello.o
: keramida@kobe:/home/keramida$ truss ./hello
: Hello, World!
: write(1,"Hello, World!\n",14)                    = 14 (0xe)
: process exit, rval = 0
: keramida@kobe:/home/keramida$

HTH,
Giorgos




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?87fx8jeixl.fsf>