CS210 PROJECT #1 Due Date: Noon Tuesday 02/22/2005 This initial project introduces students to assembly language programming style and to the use the GNU/Linux program development tools and to the so-called AT&T assembler-statement syntax. PROBLEM STATEMENT For this assignment you are asked to perform a 'migration' of an assembly language program written several years ago for another operating system and program development environment. Your job is essentially to 'translate' that older program into suitable syntax for assembly with 'as', linking with 'ld', and then executing with the Linux operating system being used in our USF labs/classrooms. The pair of program-files you are given (called 'perfect.asm' and 'cvtud.asm') were designed for use in studying a number theory question in mathematics involving the notion of a 'perfect' number (i.e., a positive integer that is equal to the sum of its factors, like six: 6 = 3 + 2 + 1). Both the main program, and its separate subroutine, make use of the x86 processor's 'division' instruction to obtain the quotient and remainder from a division operation. After you finish editing your new versions of these two files, which should be renamed 'perfect.s' and 'cvtud.s' (for conformance with the file-naming conventions used with Linux), you should type the following commands to assemble-and-link your new program: $ as perfect.s -o perfect.o $ as cvtud.s -o cvtud.o $ ld perfect.o cvtud.o -o perfect WHAT TO SUBMIT Your project-submission consists of two parts: your collection of computer-files (source-files, object-files, and the executable), plus your collection of printed text-files (source-files and screen output). Computer-files should be copied into your CS210 '/submit' directory, where they can only be accessed by your instructor, your TA, and yourself. Hardcopy printouts (with your name on them) need to be turned in to the Instructor's mailbox (in Room Harney-208) in advance of the project-submission deadline. EXTRA CREDIT The 'perfect' program as originally written lists only perfect numbers up to ten-thousand; but, by modifying the instructions used in the 'cvtud' subroutine, and changing the definition of 'maxnum', you can enhance the program's capabilities so that it shows perfect numbers up to ten-million. __________________________________________________________________ (c) Allan B. Cruse University of San Francisco Spring 2005 ; CS 210 ASSEMBLY LANGUAGE PROGRAMMING DEMO #6 ;---------------------------------------------------------------- TITLE PERFECT.ASM (Search for Perfect Numbers) COMMENT # THIS PROGRAM DISPLAYS EACH POSITIVE INTEGER SMALLER THAN TEN-THOUSAND WHICH IS EQUAL TO THE SUM OF ITS LESSER FACTORS. SUCH VALUES ARE CALLED "PERFECT NUMBERS" IN MATHEMATICS # ;** programmer: ALLAN CRUSE ;** written on: 05 OCT 1990 maxnum EQU 10000 ; bound on integers to check .386 ; use 32-bit registers ASSUME cs:code, ds:data ; declare segment uses code SEGMENT PUBLIC USE16 ;=================================== ;---------------------------------------------------------------- EXTRN cvtud:NEAR ; external conversion routine ;---------------------------------------------------------------- isperf PROC ; ; This function divides the positive integer found in EBX ; by every every smaller positive integer and accumulates ; the sum of those divisors which leave a remainder of 0. ; In case this total is equal to the integer itself, then ; the ZF flag is set on return; otherwise ZF is cleared. ; mov esi,0 ; initial sum of factors mov edi,0 ; initialize the divider nxdiv: inc edi ; increment the divider cmp edi,ebx ; smaller than integer? je finis ; no, loop is finished mov eax,ebx ; copy dividend to AX xor edx,edx ; extend to doubleword div edi ; perform the division or edx,edx ; is remainder zero? jnz nxdiv ; yes, skip addition add esi,edi ; else add this factor jmp nxdiv ; then do next division finis: cmp esi,ebx ; sum equals integer? ret ; return ZF-flag value isperf ENDP ;---------------------------------------------------------------- ;---------------------------------------------------------------- main PROC FAR mov ax,data ; address data segment mov ds,ax ; with DS register mov ebx,0 ; initial integer value nxnum: inc ebx ; next positive integer cmp ebx,maxnum ; reached maximum yet? je exit ; yes, finished looping call isperf ; else do perfect test jnz nxnum ; ZF=0? skip printing mov eax,ebx ; copy integer to EAX lea edi,outbuf ; point EDI to buffer call cvtud ; convert EAX to hex mov ah,9 ; MS-DOS print-string lea edx,outbuf ; point EDX to buffer int 21h ; request DOS service jmp nxnum ; back for next check exit: mov ah, 4Ch ; MS-DOS program exit xor al, al ; exit-status is zero int 21h ; request DOS service main ENDP ;---------------------------------------------------------------- code ENDS ;================================================ data SEGMENT USE16 ;========================================== ;---------------------------------------------------------------- outbuf DB 10 DUP (' '), 0Dh, 0Ah, '$' ; output-buffer ;---------------------------------------------------------------- data ENDS ;================================================ stak SEGMENT STACK ;========================================== ;---------------------------------------------------------------- DW 256 DUP (?) ; area reserved for stack use ;---------------------------------------------------------------- stak ENDS ;================================================ END main ; specify program entry-point ; CS 210 ASSEMBLY LANGUAGE PROGRAMMING DEMO #7 ;---------------------------------------------------------------- TITLE CVTUD (Converts a binary integer to decimal) COMMENT # THIS FILE DEFINES A PUBLIC PROCEDURE WHICH CONVERTS THE UNSIGNED 16-BIT INTEGER FOUND IN THE AX REGISTER INTO ITS REPRESENTATION AS A DECIMAL STRING AT THE LOCATION DS:DI. # ;** programmer: ALLAN CRUSE ;** written on: 27 SEP 1990 PUBLIC cvtud ; make procedure-name visible code SEGMENT PUBLIC ;======================================== ASSUME cs:code ; declare segmernt associations ;---------------------------------------------------------------- cvtud PROC NEAR push ax ; preserve caller's registers push bx push cx push dx push di mov bx,10 ; radix of the decimal system mov cx,0 ; initialize count of digits nxdiv: xor dx,dx ; extend dividend to 32-bits div bx ; perform division by radix push dx ; save remainder on the stack inc cx ; increment the digit-counter or ax,ax ; is the quotient nonzero? jnz nxdiv ; yes, generate another digit nxdgt: pop ax ; recover stacked remainder or al,'0' ; convert binary into ascii mov [di],al ; store numeral into string inc di ; and advance output index loop nxdgt ; unstack other remainders pop di ; restore caller's registers pop dx pop cx pop bx pop ax ret ; and return to the caller cvtud ENDP ;---------------------------------------------------------------- code ENDS ;================================================ END