LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-12-2006, 11:20 AM   #1
Mercurius
Member
 
Registered: Jul 2005
Distribution: Slackware 11, Solaris 10
Posts: 143

Rep: Reputation: 15
I/O in ASM


I have a problem. I adapt a simple program in ASM to write to a file a text string and it writes in binary information. Where is the problem?
Here is the code:

Code:
.include "linux.s"
.include "record-def.s"

.section .data
 .equ ST_FILE_DESCRIPTOR, -4

record1:
 .ascii "Hey diddle diddle!\0"

#This is the name of the file we will write to 
file_name:
 .ascii "heynow.txt\0"

.globl _start
_start:
 #Copy the stack pointer to %ebp
 movl %esp, %ebp
 #Allocate space to hold the file descriptor
 subl $4, %esp
 #Open the file
 movl $SYS_OPEN, %eax
 movl $file_name, %ebx
 movl $0101, %ecx  #This says to create if it doesn't exist, and open for writing
 movl $0666, %edx
 int $LINUX_SYSCALL
 #Store the file descriptor away
 movl %eax, ST_FILE_DESCRIPTOR(%ebp)

 #Write the first record
 pushl ST_FILE_DESCRIPTOR(%ebp)
 pushl $record1
 call write_record
 addl $8, %esp

 #Close the file descriptor
 movl $SYS_CLOSE, %eax
 movl ST_FILE_DESCRIPTOR(%ebp), %ebx
 int $LINUX_SYSCALL

 #Exit the program
 movl $SYS_EXIT, %eax
 movl $0, %ebx
 int $LINUX_SYSCALL
linux.s:
Code:
#Common Linux Definitions

#System Call Numbers
.equ SYS_EXIT, 1
.equ SYS_READ, 3
.equ SYS_WRITE, 4
.equ SYS_OPEN, 5
.equ SYS_CLOSE, 6
.equ SYS_BRK, 45

#System Call Interrupt Number
.equ LINUX_SYSCALL, 0x80

#Standard File Descriptors
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2

#Common Status Codes
.equ END_OF_FILE, 0
And finally record-def.s:
Code:
.equ RECORD_SIZE, 18

#PURPOSE: This function writes a record to
#         the given file descriptor
#
#INPUT:   The file descriptor and a buffer
#
#OUTPUT:  This function produces a status code
#
#STACK LOCAL VARIABLES
.equ ST_WRITE_BUFFER, 8
.equ ST_FILEDES, 12
.section .text
.globl write_record
.type write_record, @function
write_record:
 pushl %ebp
 movl %esp, %ebp

 pushl %ebx
 movl $SYS_WRITE, %eax
 movl ST_FILEDES(%ebp), %ebx
 movl ST_WRITE_BUFFER(%ebp), %ecx
 movl $RECORD_SIZE, %edx
 int $LINUX_SYSCALL

#NOTE - %eax has the return value, which we will
#give back to our calling program
popl %ebx

movl %ebp, %esp
popl %ebp
ret
 
Old 11-12-2006, 12:18 PM   #2
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Your program is setup in a complicated way.

Let's see...
First off, the null terminator is not necessary in your record1 (especially since you don't include it in your RECORD_SIZE)

What do you mean by "it writes in binary information". When I try it, it works fine. If you try
Code:
mypromptislongorcolorful$ file heynow.txt
heynow.txt: ASCII text, with no line terminators
mypromptislongorcolorful$ cat heynow.txt
mypromptislongorcolorful$ngorcolorful$
                          ^
The only thing weird is that there is no newline at the end of the string. This means that "cat heynow.txt" will output the contents and probably be overwritten by your shell prompt. The location of the cursor is probably where the carrot mark is shown. All you need to do to remedy this is put a "\n" (newline) at the end of record1. Then make your RECORD_SIZE 19.
 
Old 11-12-2006, 12:22 PM   #3
Mercurius
Member
 
Registered: Jul 2005
Distribution: Slackware 11, Solaris 10
Posts: 143

Original Poster
Rep: Reputation: 15
I mean, if I assemble it with as, then link it with ld, it writes a binary file not a normal text file ...
 
Old 11-12-2006, 01:28 PM   #4
Mercurius
Member
 
Registered: Jul 2005
Distribution: Slackware 11, Solaris 10
Posts: 143

Original Poster
Rep: Reputation: 15
Right, it works. How could I simplify the program? On what parts?
 
Old 11-12-2006, 01:30 PM   #5
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by Mercurius
I mean, if I assemble it with as, then link it with ld, it writes a binary file not a normal text file ...
There is no fundamental difference between a "text" file and a "binary" file (a better way to say this is that a text file is a special kind of binary file). Did you try adding the newline? What's the output when you do "file heynow.txt"? How about the output when you do "hexdump -C heynow.txt"?
 
Old 11-12-2006, 01:34 PM   #6
Mercurius
Member
 
Registered: Jul 2005
Distribution: Slackware 11, Solaris 10
Posts: 143

Original Poster
Rep: Reputation: 15
Well, it works now, but im looking to simplify the program. I added the newline so it works now good. It was a binary file beacause I filled accidentaly 300 bytes full of zero after the string so it read the file as binary.
 
Old 11-12-2006, 06:01 PM   #7
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by Mercurius
Right, it works. How could I simplify the program? On what parts?
I guess I didn't understand the point of write_record. Will it be used when repeatedly writing records to a file? If so, are you guaranteed that each record is exactly RECORD_SIZE bytes in length? Usually when you are guaranteeing a specific number of bytes each time, your output should be "binary" (for example the contents of a struct or something). Second, the RECORD_SIZE would most likely remain fixed (e.g., to the size of the struct). But you are outputting an ASCII string. In order to keep RECORD_SIZE constant, you'd need to make record1 "Hey diddle diddle\n" (i.e., replace the exclamation point).

The other thing that I find complicated is the file structure and style. I would recommend using macros instead of memory for constants (i.e., C style macros with gcc and the .S suffix) in your header files. More importantly, why do you include the record-def.s file if you intend for write_record to be a standalone function (which I assume after the first paragraph ). If it's not a standalone-function, does it become a useless wrapper for write()?

So I guess the short version is, why are you writing ASCII data with a fixed size record-writing function? If it's not a fixed-size record-writing function, what is it?
 
Old 11-14-2006, 08:41 AM   #8
Mercurius
Member
 
Registered: Jul 2005
Distribution: Slackware 11, Solaris 10
Posts: 143

Original Poster
Rep: Reputation: 15
Well, baiscly it's none of that. It is just a simple ASM program to write to a file a certain text. That's all. What do you think, how can I simplify it?
 
Old 11-14-2006, 12:02 PM   #9
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
I do not think that all you want to do is write text to a file, as the simplest (an most readable) way to do so would be

test.S:
Code:
#include <asm/unistd.h>
#define syscall int $0x80

.section .data

record1:
	.ascii "Hey diddle diddle!\n"
	len = . - record1

file_name:
	.asciz "heynow.txt"

.globl _start
_start:

# fd = open(file_name, O_WRONLY|O_CREAT, 0666)
	movl $__NR_open, %eax
	movl $file_name, %ebx
	movl $0101, %ecx
	movl $0666, %edx
	syscall

# write(fd, record1, len)
	movl %eax, %ebx
	movl $__NR_write, %eax
	movl $record1, %ecx
	movl $len, %edx
	syscall

# close(fd)
	movl $__NR_close, %eax
	syscall

# exit(0)
	movl $__NR_exit, %eax
	movl $0, %ebx
	syscall
assembled and linked with the commands:
Code:
gcc -c test.S
ld test.o -o test
Notice how with #define macros, the end-product doesn't have extra symbols (i.e., SYS_OPEN, SYS_WRITE, etc.) floating around. You don't have to retabulate the syscall numbers, as that's already done in /usr/include/asm/unistd.h. The variable holding the length of record1 will automatically change as you change the size of the string. Additionally, since you have so few variables, you don't need to put the file descriptor on the stack, and you don't have the overhead of an extra function call.

Last edited by osor; 11-16-2006 at 07:02 PM.
 
Old 11-15-2006, 11:26 PM   #10
Mercurius
Member
 
Registered: Jul 2005
Distribution: Slackware 11, Solaris 10
Posts: 143

Original Poster
Rep: Reputation: 15
Well, I understand what you say, thanks a lot. It is my first time writing in ASM so I am studying the Book Programming from the Ground Up. That is why I used as and ld. But as I see now it is easyer to do it as you did, even compiled with gcc.
 
Old 11-16-2006, 07:02 PM   #11
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by Mercurius
...I used as and ld. But as I see now it is easyer to do it as you did, even compiled with gcc.
Just a quick point: "compiling" with gcc (in the way I did) is not any different from using gas (which is actually called by gcc behind the scenes), except for the processing of C-style macros, which are more readable/convenient (at least to me) than .macro and .endm.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
asm/uaccess.h eltn Programming 2 10-22-2004 06:14 PM
Jumping in asm LongName Programming 3 08-31-2004 07:27 PM
How to use C functions in asm? LongName Programming 4 08-29-2004 12:25 AM
asm question karlan Programming 6 07-16-2004 11:54 AM
ASM question zWaR Programming 2 06-26-2004 11:42 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:38 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration