From: "M. Schulter" Newsgroups: comp.os.msdos.djgpp Subject: DJGPP humor: lightyr.s (long long) Date: 25 Sep 1997 23:15:10 GMT Organization: Value Net Internetwork Services Inc. Lines: 205 Message-ID: <60er9u$5qp$2@vnetnews.value.net> NNTP-Posting-Host: value.net To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk Hi, there. Here's a standalone GAS program with a bit of humor: please enjoy. I'm not sure if the fact this was created in Emacs asm mode has anything to do with the result, but it's sure a nice environment to explore a new language. Also, this program includes a 'long long' type displayed with _printf. Thanks to Andrew Crabtree for a suggestion I used in revising this program: using a variable _stacksave to restore the value of %esp at the end rather than reseting it after every printf. I'd be curious to learn, by the way, if there's any guideline in more ambitious programs on how large one should allow the stack to grow, or how often one should restore %esp. Most appreciatively, Margo /* * This standalone GAS file uses a long long type to calculate * and store the distance of a light year measured in meters. * Note the C-style output with _printf from within an assembler * program; DJGPP makes possible this style, also used by some * Linux programmers. * * This code actually compiles successfully for me with * DJGPP 2.01 (gcc 2.7.2.1, bnu 2.8.1): * * gcc -o lightyr.exe lightyr.s * * This file is released under the GNU General Public * License (GPL), but is _not_ GNU software. * * Margo Schulter * mschulter AT value DOT net * September 24, 1997 */ .file "lightyr.s" .data .global _result # long long int for result .align 3 _result: .int 0 .int 0 .global _light_second # distance in meters .align 2 _light_second: .int 299792458 .global _minute # 60 seconds in one minute .align 2 _minute: .int 60 .global _hour # 60 minutes in one hour .align 2 _hour: .int 60 .global _day # 24 hours in one day .align 2 _day: .int 24 .global _year # 365 whole days in one year .align 2 _year: .int 365 .global _leaptime # extra 5 hours, 48 minutes, 46 seconds .align 2 _leaptime: .int 20926 .global _seconds_in_year # global for seconds in year .align 2 _seconds_in_year: .int 0 .global _stacksave # initial value of %esp, to restore _stacksave: # before ret (thanks to Andy Crabtree) .int 0 /* * Now for our strings to display, most in PostScript-like style * with \nnn as an "anti-spoiler" device */ string0: .ascii "\n\nThe velocity of light is %i meters per second.\n\0" string1: .ascii "There are about %i seconds in a year.\n\0" string2: .ascii "Therefore a light year is approximately %Ld meters.\n\0" string3: .ascii "\n\n\52\52\52\52\52\52\52\52\52\52\52\52\52\0" string4: .ascii "\040\42\066\064\055\142\151\164\0" string5: .ascii "\040\151\156\164\145\147\145\162\163\040\147\157\040\0" string6: .ascii "\141\040\140\154\157\156\147\040\154\157\156\147\047\0" string7: .ascii "\040\167\141\171\42\040\52\52\52\52\52\52\52\52\52\0" string8: .ascii "\52\52\52\0" string9: .ascii "\n\52\52\52\52\52\52\52\52\52\040\107\145\0" stringa: .ascii "\164\040\164\150\141\164\040\145\170\164\162\141\040\160\0" stringb: .ascii "\145\164\141\155\145\164\145\162\040\157\146\040\155\151\0" stringc: .ascii "\154\145\141\147\145\040\167\151\164\150\040\107\101\0" stringd: .ascii "\123\041\040\52\52\52\52\52\52\52\52\52\n\n\0" .text .global _main _main: movl _light_second, %eax # move variable into %eax movl _minute, %ebx # start calculating seconds in year imull _hour, %ebx # %ebx = 60*60 imull _day, %ebx # %ebx = 60*60*24 imull _year, %ebx # %ebx = 60*60*24*365 addl _leaptime, %ebx # %ebx = (60*60*24*365) + 20926 movl %ebx, _seconds_in_year # store %ebx into variable imull %ebx # GAS syntax for result in %edx:%eax movl %edx, _result+4 # move %edx part into upper 4 bytes # of our `long long' variable movl %eax, _result # and %eax into lower 4 bytes /* * Now that we've done our calculation, we get to have fun * showing strings, sort of like in PostScript: put string * on stack, and call _printf. This cumulatively decrements * %esp, but we can restore _stacksave_ before exiting _main. * Really neat for a 2GL . */ movl %esp, _stacksave # store current value of %esp # in _stacksave to restore at end # of our _main pushl $string3 call _printf pushl $string4 call _printf pushl $string5 call _printf pushl $string6 call _printf pushl $string7 call _printf pushl $string8 call _printf /* * Now we move from the "desktop publishing" stuff to reporting * our results: arguments for _printf go on stack, rightmost * argument first, e.g. variable, then string. */ pushl _light_second pushl $string0 call _printf pushl _seconds_in_year pushl $string1 call _printf pushl _result+4 # first push upper 4 bytes pushl _result # then lower 4 bytes pushl $string2 # (could this order be because call _printf # i386 is little-endian?) /* * With our results reported, it's back to some more desktop * publishing fun: don't worry, PostScript and TeX still have * their uses. */ pushl $string9 call _printf pushl $stringa call _printf pushl $stringb call _printf pushl $stringc call _printf pushl $stringd call _printf movl _stacksave, %esp # restore stack pointer ret # leave program