//---------------------------------------------------------------- // out2file.s // // This program shows how Linux system-calls can be used to // create a new text file in the current working directory. // If any system-call fails, the address for an appropriate // diagnostic-message is pushed onto the stack, followed by // the address of a procedure that will display the message // and then terminates the program (so in case of an error, // the next-encountered 'return' instruction would transfer // control to our common error-handling routine, instead of // returning back to our 'main' function). // // assemble with: $ as out2file.s -o out2file.o // and link with: $ ld out2file.o -o out2file // // programmer: ALLAN CRUSE // written on: 26 OCT 2003 // revised on: 12 APR 2005 //---------------------------------------------------------------- # manifest constants .equ STDERR, 2 .equ sys_EXIT, 1 .equ sys_WRITE, 4 .equ sys_OPEN, 5 .equ sys_CLOSE, 6 .equ O_CREAT, 0100 .equ O_TRUNC, 01000 .equ O_WRONLY, 01 .equ S_ACCESS, 00600 .section .text #----------------------------------------------------------------- _start: call create_file call output_data call commit_file call notify_user call termination #----------------------------------------------------------------- .section .data #----------------------------------------------------------------- flags: .int O_CREAT | O_WRONLY | O_TRUNC access: .int S_ACCESS # define file-permissions handle: .int -1 # used as file identifier filename: .asciz "mycookie.dat" # name for file to create #----------------------------------------------------------------- fileinfo: .ascii "Computer Science 210\n" .ascii "Spring 2005\n" .ascii "University of San Francisco\n" .equ infosize, . - fileinfo #----------------------------------------------------------------- .section .text #----------------------------------------------------------------- create_file: movl $sys_OPEN, %eax # service-number movl $filename, %ebx # address of name movl flags, %ecx # mode-settings movl access, %edx # file-permissions int $0x80 # enter the kernel movl %eax, handle # save return-code or %eax, %eax # check: success? jns creatx # yes, finished pushl $size05 # message-length pushl $fail05 # message-address pushl $exitmsg # function-address creatx: ret # transfer control #----------------------------------------------------------------- fail05: .ascii "Could not create file.\n\n" .equ size05, . - fail05 #----------------------------------------------------------------- output_data: movl $sys_WRITE, %eax # service-number movl handle, %ebx # specify the file movl $fileinfo, %ecx # buffer's address movl $infosize, %edx # buffer's length int $0x80 # enter the kernel or %eax, %eax # check: success? jns writex # yes, finished pushl $size04 # message-length pushl $fail04 # message-address pushl $exitmsg # function-address writex: ret # transfer control #----------------------------------------------------------------- fail04: .ascii "Could not write to file.\n\n" .equ size04, . - fail04 #----------------------------------------------------------------- commit_file: movl $sys_CLOSE, %eax # service-number movl handle, %ebx # specify the file int $0x80 # enter the kernel or %eax, %eax # check: success? jns closex # yes, finished pushl $size06 # message-length pushl $fail06 # message-address pushl $exitmsg # function-address closex: ret # transfer control #----------------------------------------------------------------- fail06: .ascii "Could not close file.\n\n" .equ size06, . - fail06 #----------------------------------------------------------------- #----------------------------------------------------------------- notify_user: movl $sys_WRITE, %eax # service-number movl $STDERR, %ebx # device-handle movl $message, %ecx # buffer's address movl $msgsize, %edx # buffer's length int $0x80 # enter the kernel ret # transfer control #----------------------------------------------------------------- message: .ascii "\nNew file successfully created\n\n" .equ msgsize, . - message #----------------------------------------------------------------- # # This is our common error-handling routine, which only executes # in case one of our kernel system-calls returns a failure-code. # Upon entry, this routine assumes that the address of a message # (and the length of that message) will be found atop the stack. # #----------------------------------------------------------------- exitmsg: # first show the name of this program (so a user # will know the source of the message to follow) movl $sys_WRITE, %eax # service-number movl $STDERR, %ebx # device-handle movl $exitfmt, %ecx # string's address movl $fmtsize, %edx # string's length int $0x80 # enter the kernel # then show the diagnostic error-message (whose # address and length are popped from the stack) movl $sys_WRITE, %eax # service-number movl $STDERR, %ebx # device-handle popl %ecx # string's address popl %edx # string's length int $0x80 # enter the kernel # finally, fall through to the program-exit code termination: movl $sys_EXIT, %eax # service-number xorl %ebx, %ebx # return-code int $0x80 # enter the kernel #----------------------------------------------------------------- exitfmt: .ascii "\nout2file: " .equ fmtsize, . - exitfmt #----------------------------------------------------------------- .globl _start .end