From owner-freebsd-questions@FreeBSD.ORG Thu Nov 12 17:45:15 2009 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0A7FC1065694 for ; Thu, 12 Nov 2009 17:45:15 +0000 (UTC) (envelope-from keramida@ceid.upatras.gr) Received: from poseidon.ceid.upatras.gr (poseidon.ceid.upatras.gr [150.140.141.169]) by mx1.freebsd.org (Postfix) with ESMTP id 793808FC1C for ; Thu, 12 Nov 2009 17:45:14 +0000 (UTC) Received: from mail.ceid.upatras.gr (unknown [10.1.0.143]) by poseidon.ceid.upatras.gr (Postfix) with ESMTP id 25930EB4839; Thu, 12 Nov 2009 19:45:13 +0200 (EET) Received: from localhost (europa.ceid.upatras.gr [127.0.0.1]) by mail.ceid.upatras.gr (Postfix) with ESMTP id 1A07E452BE; Thu, 12 Nov 2009 19:45:13 +0200 (EET) X-Virus-Scanned: amavisd-new at ceid.upatras.gr Received: from mail.ceid.upatras.gr ([127.0.0.1]) by localhost (europa.ceid.upatras.gr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Csr6Z4x+-XJ8; Thu, 12 Nov 2009 19:45:12 +0200 (EET) Received: from kobe.laptop (ppp-94-64-255-253.home.otenet.gr [94.64.255.253]) by mail.ceid.upatras.gr (Postfix) with ESMTP id AD57F452A4; Thu, 12 Nov 2009 19:45:12 +0200 (EET) Received: from kobe.laptop (kobe.laptop [127.0.0.1]) by kobe.laptop (8.14.3/8.14.3) with ESMTP id nACHjBS1084589 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 12 Nov 2009 19:45:11 +0200 (EET) (envelope-from keramida@ceid.upatras.gr) Received: (from keramida@localhost) by kobe.laptop (8.14.3/8.14.3/Submit) id nACHjBLf084588; Thu, 12 Nov 2009 19:45:11 +0200 (EET) (envelope-from keramida@ceid.upatras.gr) From: Giorgos Keramidas To: David Jackson References: <4AFB13D9.9050507@gmail.com> Date: Thu, 12 Nov 2009 19:45:10 +0200 In-Reply-To: <4AFB13D9.9050507@gmail.com> (David Jackson's message of "Wed, 11 Nov 2009 14:43:21 -0500") Message-ID: <87fx8jeixl.fsf@kobe.laptop> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (berkeley-unix) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: freebsd-questions@freebsd.org Subject: Re: Problems with FreeBSD assembly X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Nov 2009 17:45:15 -0000 On Wed, 11 Nov 2009 14:43:21 -0500, David Jackson 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