Difference between revisions of "CSC231 Homework Solutions 2017"
Line 981: | Line 981: | ||
</source> | </source> | ||
<!-- ================================================================= --> | <!-- ================================================================= --> | ||
− | + | ||
− | =funcs.c= | + | =Homework 9: funcs.c= |
<br /> | <br /> | ||
::<source lang="c"> | ::<source lang="c"> | ||
Line 1,051: | Line 1,051: | ||
} | } | ||
</source> | </source> | ||
− | =hanoi.asm= | + | =Homework 9: hanoi.asm= |
<br /> | <br /> | ||
::<source lang="asm"> | ::<source lang="asm"> | ||
Line 1,186: | Line 1,186: | ||
</source> | </source> | ||
− | + | ||
<br /> | <br /> | ||
<br /> | <br /> |
Revision as of 06:34, 4 May 2017
--D. Thiebaut (talk) 17:57, 22 April 2017 (EDT)
Contents
Problem 1
;;; mystery.asm ;;; D. Thiebaut ;;; ;;; To assemble, link, and run: ;;; nasm -f elf mystery.asm ;;; ld -melf_i386 -o mystery mystery.o ;;; ./mystery ;;; section .data Hello db "Hello there!", 10, 10 HelloLen equ $-Hello section .text global _start _start: ;;; print Hello and a space after it mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, Hello ; address of message to print mov edx, 6 ; print only 6 chars int 0x80 ;;; print ! and two line feed chars mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, Hello+11 ; address of ! char mov edx, 3 ; print only 3 chars int 0x80 ;;; exit mov ebx, 0 mov eax, 1 int 0x80
hw1.asm
;;; hw1.asm ;;; D. Thiebaut ;;; ;;; To assemble, link, and run: ;;; nasm -f elf hw1.asm ;;; ld -melf_i386 -o hw1 hw1.o ;;; ./hw1 ;;; section .data msg db " CSC231 Assembly " linefeed db 10 dashline db "------------------" lineLen equ $-dashline section .text global _start _start: ;;; print message mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, dashline ; address of message to print mov edx, lineLen ; # of chars to print int 0x80 mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, dashline ; address of message to print mov edx, lineLen ; # of chars to print int 0x80 mov eax, 4 ;print line-feed mov ebx, 1 mov ecx, linefeed mov edx, 1 int 0x80 mov eax, 4 ; write ---- mov ebx, 1 ; stdout mov ecx, dashline ; address of message to print mov edx, 9 ; # of chars to print int 0x80 mov eax, 4 ; write message mov ebx, 1 ; stdout mov ecx, msg ; address of message to print mov edx, lineLen ; # of chars to print int 0x80 mov eax, 4 ; write ---- mov ebx, 1 ; stdout mov ecx, dashline ; address of message to print mov edx, 9 ; # of chars to print int 0x80 mov eax, 4 ;print line-feed mov ebx, 1 mov ecx, linefeed mov edx, 1 int 0x80 mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, dashline ; address of message to print mov edx, lineLen ; # of chars to print int 0x80 mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, dashline ; address of message to print mov edx, lineLen ; # of chars to print int 0x80 mov eax, 4 ;print line-feed mov ebx, 1 mov ecx, linefeed mov edx, 1 int 0x80 ;;; exit mov ebx, 0 mov eax, 1 int 0x80
hw2.asm
;;; ; ; hw2sol.asm ;;; ; ; D. Thiebaut ;;; ; ; ;;; ; ; extern _printDec extern _printString extern _println extern _getInput section .data prompt db "> " promptLen equ $-prompt ansStr db "ans = " ansStrLen equ $-ansStr a dd 0 b dd 0 c dd 0 ans dd 0 section .text global _start _start: ;; display prompt mov ecx, prompt mov edx, promptLen call _printString ;; get a call _getInput mov dword[a], eax ;; display prompt mov ecx, prompt mov edx, promptLen call _printString ;; get b call _getInput mov dword[b], eax ;; display prompt mov ecx, prompt mov edx, promptLen call _printString ;; get c call _getInput mov dword[c], eax ;; ----------------------------------- ;; computation: ans = 2*(a-b) + 3*c ;; ----------------------------------- ; your code will go here... ;; ----------------------------------- ;; display "ans =" ;; ----------------------------------- mov ecx, ansStr mov edx, ansStrLen call _printString ;; ----------------------------------- ;; display ans variable ;; ----------------------------------- mov eax, dword[ans] call _printDec call _println call _println ;;; exit mov ebx, 0 mov eax, 1 int 0x80
Teller.asm
;;; ; teller.asm ;;; ; D. Thiebaut ;;; ; ;;; ; Demo of a teller machine program. ;;; ; To assemble, link, and run: ;;; ; nasm -f elf teller.asm ;;; ; ld -melf_i386 -o teller teller.o 231Lib.o ;;; ; ./teller ;;; ; ;;; extern functions that will be linked to this program ;;; ; contained in 231Lib.asm extern _printDec extern _printString extern _println extern _getInput ;;; ------------------------------------------------------ ;;; DATA SECTION ;;; ------------------------------------------------------ section .data amount dd 139 no20s dd 0 no10s dd 0 no5s dd 0 no1s dd 0 msg db "amount? " MSGLEN equ $-msg ;;; ------------------------------------------------------ ;;; CODE SECTION ;;; ------------------------------------------------------ section .text global _start _start: ;;; get amount from the user mov ecx, msg mov edx, MSGLEN call _printString call _getInput mov dword[amount], eax call _println ;;; Break down amount in 20s, 10s, 5s, and 1s mov eax, dword[amount] mov edx, 0 mov ebx, 20 mov eax, dword[amount] call break mov dword[no20s], eax mov ebx, 10 mov eax, dword[amount] call break mov dword[no10s], eax mov ebx, 5 mov eax, dword[amount] call break mov dword[no5s], eax mov eax, dword[amount] mov dword[no1s], eax mov eax, dword[no20s] call _printDec call _println mov eax, dword[no10s] call _printDec call _println mov eax, dword[no5s] call _printDec call _println mov eax, dword[no1s] call _printDec call _println ;;; exit mov ebx, 0 mov eax, 1 int 0x80 ;;; sum: gets 2 ints in eax and ebx and returns the sum in ;;; eax. sum: add eax, ebx, ret ;;; break: gets amount in eax, divider in ebx, divides, ;;; and puts remainder in [amount] and quotient in eax break: mov edx, 0 div ebx mov dword[amount], edx ret
hw5_1.asm
;;; ; hw5_1.asm ;;; ; D. Thiebaut ;;; ; ;;; ; Prints 10 lines of Pascal triangle. ;;; ; ;;; ; to assemble and run: ;;; ; ;;; ; nasm -f elf -F stabs hw5_1.asm ;;; ; ld -melf_i386 -o hw5_1 hw5_1.o ;;; ; ./hw5_1 ;;; ; ------------------------------------------------------------------- extern _printString extern _getInput extern _println ;;; ------------------------------------------------------------ ;;; data areas ;;; ------------------------------------------------------------ section .data prompt db "> " stars db "******************************************" N dd 0 saveECX dd 0 ;;; ------------------------------------------------------------ ;;; code area ;;; ------------------------------------------------------------ section .text global _start _start: ;;; get N from user mov ecx, prompt mov edx, 2 call _printString call _getInput mov dword[N], eax ;;; ------------------------------------------------- ;;; print opening triangle mov ecx, dword[N] for0: mov dword[saveECX], ecx mov edx, dword[N] sub edx, ecx inc edx mov ecx, stars call _printString call _println mov ecx, dword[saveECX] loop for0 ;;; ------------------------------------------------- ;;; print square mov ecx, dword[N] for1: mov dword[saveECX], ecx ;;; print a line of N stars mov ecx, stars mov edx, dword[N] call _printString call _println mov ecx, dword[saveECX] loop for1 ;;; ------------------------------------------------- ;;; print closing triangle mov ecx, dword[N] for2: mov dword[saveECX], ecx mov edx, ecx mov ecx, stars call _printString call _println mov ecx, dword[saveECX] loop for2 ;;; exit() mov eax,1 mov ebx,0 int 0x80 ; final system call
hw5_2.sh
#! /bin/bash # hw5_2.sh # D. Thiebaut # gets a number of the command line and prints a triangle # a square and a triangle with the width equal to the value # of the number. N=$1 for i in $( seq 1 $N ) ; do for j in $( seq 1 $i ) ; do echo -n "*" done echo "" done for i in $( seq 1 $N ) ;do for j in $( seq 1 $N ) ; do echo -n "*" done echo"" done exit for i in $( seq 1 $N ) ;do top=$( expr $N - $i + 1 ) for j in $( seq 1 $top ) ; do echo -n "*" done echo"" done
GameOfLife.asm
;;; ; GameOfLife.asm ;;; ; Authors: D. Thiebaut and CSC231 Class ;;; ; ;;; ; Implements a 1-dimensional version of ;;; ; Conway's Game of life. ;;; ; Note that because we do not "know" yet ;;; ; how to test or to use functions, the code ;;; ; is not as efficient as it could be. ;;; ; ;;; ; to assemble and run: ;;; ; ;;; ; nasm -f elf -F stabs GameOfLife.asm ;;; ; ld -melf_i386 -o GameOfLife GameOfLife.o ;;; ; ./GameOfLife ;;; ; ------------------------------------------------------------------- ;;; ------------------------------------------------------------ ;;; data areas ;;; ------------------------------------------------------------ section .data ;;; the current dish with its cells. We use 0 and 1 to ;;; indicate dead and live cells, respectively. %include "dishArray.inc" ;;; the new generation of cells. That's the "future" of the ;;; cells in the dish. We make it the same size as dish, and ;;; fill it with N dead cells. newGen times N db 0 ;;; dishP is a string that will contain ' ' or '!' for ;;; each 0 or 1 in dish. dishP times N db ' ' db 10 ; add a \n at the end ; of dishP generation dd 0 ; save ecx from for generation loop i dd 0 ; used by for loops ;;; ------------------------------------------------------------ ;;; code area ;;; ------------------------------------------------------------ section .text global _start _start: main: ;;; ------------------------------------------------------------- ;;; print( dish ) ;; first we copy dish into dishP and at the same ;; time replace 0 by ' ' and 1 by '!' ;;; for i in range( N ): mov esi, dish mov edi, dishP mov dword[i], 0 forPrint: cmp dword[i], N jge forPrintEnd mov al, byte[esi] add al, ' ' ;0 becomes ' ', 1 becomes '!' mov byte[edi], al inc esi ;esi points to next byte in dish inc edi ;edi points to next byte in dispP ;; i++, loop back inc dword[i] jmp forPrint forPrintEnd: ;; print dishP as a string. mov eax, 4 ;prints dishP to screen mov ebx, 1 mov ecx, dishP ;dishP address mov edx, N+1 ;+1 to include the \n int 0x80 ;;; ----------------------------------------------------------- ;;; for generation in range( maxGen ): mov dword[generation], 0 forGen: mov eax, dword[generation] cmp eax, dword[maxGen] jge forGenEnd ;;; ----------------------------------------------------------- ;;; newGen = life( dish, N ) ;;; newGen[0] = 0 ;;; newGen[N-1] = 0 mov byte[newGen], 0 mov byte[newGen+N-1], 0 ;;; ----------------------------------------------------------- ;;; for i in range( 0, N ): mov esi, dish mov edi, newGen mov dword[i], 0 forLife: cmp dword[i], N jge forLifeEnd ;;; ----------------------------------------------------------- ;;; fate = dish[i-1] ^ dish[i+1] ;;; newGen[i] = fate mov al, byte[esi-1] xor al, byte[esi+1] mov byte[edi], al inc esi inc edi inc dword[i] jmp forLife forLifeEnd: ;;; ----------------------------------------------------------- ;;; dish = newGen mov dword[i],0 mov esi, newGen mov edi, dish forMove: cmp dword[i], N jge forMoveEnd mov al, byte[esi] ;copy newGen[i] to dish[i] mov byte[edi], al inc esi inc edi inc dword[i] loop forMove forMoveEnd: ;;; ------------------------------------------------------------- ;;; print( dish ) ;; first we copy dish into dishP and at the same ;; time replace 0 by ' ' and 1 by '!' ;;; for i in range( N ): mov esi, dish mov edi, dishP mov dword[i], 0 forPrint2: cmp dword[i], N jge forPrintEnd2 mov al, byte[esi] add al, ' ' ;0 becomes ' ', 1 becomes '!' mov byte[edi], al inc esi ;esi points to next byte in dish inc edi ;edi points to next byte in dispP inc dword[i] jmp forPrint2 forPrintEnd2: ;; print dishP as a string. mov eax, 4 ;prints dishP to screen mov ebx, 1 mov ecx, dishP ;dishP address mov edx, N+1 ;+1 to include the \n int 0x80 ;;; ready to loop back to forGen inc dword[generation] jmp forGen forGenEnd: ;;; exit() exit: mov eax,1 mov ebx,0 int 0x80 ; final system call
hw7_1.C
#include <stdio.h> #include <stdlib.h> #include <string.h> int main( int argc, char *argv[] ) { int n, i, name; char sentence[100]; char stars[100]; if ( argc < 2 ) { printf( "Syntax: %s string [string...]\n", argv[0] ); exit( 1 ); } strcpy( sentence, "* " ); for ( i = 1; i < argc; i++ ) { if ( i > 1 ) strcat( sentence, " " ); strcat( sentence, argv[i] ); } strcat( sentence, " *" ); // printf( "%s\n", sentence ); n = (int) strlen( sentence ); strcpy( stars, "*" ); for ( i=0; i<strlen( stars)-1; i++ ) strcat( stars, "*" ); for ( i=0; i< n-1; i++ ) { stars[i+1] = '\0'; printf( "%s\n", stars ); stars[i+1] = '*'; } printf( "%s\n", sentence ); for ( i=n-2; i>= 0; i-- ) { stars[i+1] = '\0'; printf( "%s\n", stars ); stars[i+1] = '*'; } return 0; }
hw7_2.asm
;;; ; ------------------------------------------------------------------- ;;; ; hw4b.asm ;;; ; Julia Burch ;;; ; 231a-aa ;;; ; ;;; ; Computes and prints the first 10 rows of Pascal's triangle. ;;; ; OUTPUT: ;;; ; 1 0 0 0 0 0 0 0 0 0 ;;; ; 1 1 0 0 0 0 0 0 0 0 ;;; ; 1 2 1 0 0 0 0 0 0 0 ;;; ; 1 3 3 1 0 0 0 0 0 0 ;;; ; 1 4 6 4 1 0 0 0 0 0 ;;; ; 1 5 10 10 5 1 0 0 0 0 ;;; ; 1 6 15 20 15 6 1 0 0 0 ;;; ; 1 7 21 35 35 21 7 1 0 0 ;;; ; 1 8 28 56 70 56 28 8 1 0 ;;; ; 1 9 36 84 126 126 84 36 9 1 ;;; ; to assemble and run: ;;; ; ;;; ; nasm -f elf -F stabs hw4b.asm ;;; ; gcc -o hw4b driver.c asm_io.o hw4b.o ;;; ; ./hw4b ;;; ; ------------------------------------------------------------------- ;; %include files here... extern _printDec extern _println extern _printString ;;; ------------------------------------------------------------ ;;; data areas ;;; ------------------------------------------------------------ section .data shift db 0 pascal db 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 temp dd 0 space db 9 rows equ 10 ;;; ------------------------------------------------------------ ;;; code area ;;; ------------------------------------------------------------ section .text global _start _start: ;; move first line of Pascal into edi, then rows into ecx ;; to initialize and run for loop 10 times. mov edi, pascal mov ecx, rows main: ;; store ecx in a temporary variable, move rows into ecx to initialize ;; and run print_triangle loop. Move the first line into edi ;; and 0 into esi. push ecx mov ecx, rows mov edi, pascal mov esi, 0 print_triangle: ;; print the int in al, print tab and then clear ;; tab from register. push ecx mov al, byte[edi+esi] call _printDec mov ecx, space mov edx, 1 call _printString mov eax, 0 inc esi pop ecx loop print_triangle ;; print a new line call _println ;; load newly calculated pascal line into edi, then shift the row mov edi, pascal mov esi, shift mov ecx, rows-1 calculate: ;; move pascal digit into al, add it to previous row's, store the value mov al, byte[edi+ecx] add al, byte[esi+ecx] mov byte[edi+ecx], al loop calculate ;; restore value of ecx for loop pop ecx loop main ;;; exit() mov ebx, 0 mov eax, 1 int 0x80
hw7_3.asm (mystery program)
;;; helloWorld.asm ;;; D. Thiebaut ;;; ;;; To assemble, link, and run: ;;; nasm -f elf helloWorld.asm ;;; ld -melf_i386 -o helloWorld helloWorld.o ;;; ./helloWorld ;;; section .data db "Mystery", 0 msg1 db "Vive le chacalot au lait!", 0 msg2 db "Assembly is fun!", 0 msg3 db 0x01, 0x02, 0x03 x dd 128 y dd 64 HelloLen equ $-msg1 section .text _mystery: ;;; print message add byte[msg1+10],'o'-'a' add byte[msg1+12],'o'-'a' add byte[msg1+14],'a'-'o' mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, msg1+8 mov edx, 8 ; # of chars to print int 0x80 mov eax, dword[x] add eax, 0xFFFFFFFF xor ebx, ebx mov bx, word[y] shl bx,16 mov edx, 0x12345678 mov dx, ax mov ecx, 10 loop there there: ;;; exit mov ebx, 0 mov eax, 1 int 0x80
hw8_1.c
#include <stdio.h> #include <stdlib.h> #include <string.h> void main( int argc, char *argv[] ) { char *marker1, *marker2, *DNA; char *fileName; if (argc < 4 ) { printf( "syntax: %s marker1 marker2 DNA\n", argv[0] ); return; } marker1 = argv[1]; marker2 = argv[2]; DNA = argv[3]; //--- print the markers and DNA --- /* (for debugging purposes) printf( "Marker1 = %s\n", marker1 ); printf( "Marker2 = %s\n", marker2 ); if ( strlen( DNA ) > 80 ) printf( "DNA = %.*s...%s (%d bases)\n\n", 10, DNA, DNA+((int)strlen(DNA)-10), (int) strlen( DNA) ); else printf( "DNA = %s\n\n", DNA ); */ //--- add your code below this point --- char *first, *second; first = strstr( DNA, marker1 ); if ( first == NULL ) { printf( "%s\n", DNA ); return; } second = strstr( first+1, marker2 ); if ( second == NULL ) { printf( "%s\n", DNA ); return; } char *p; for ( p= first; p < second+strlen(marker2); p++ ) *p = '-'; printf( "%s\n", DNA ); }
hw8_2.asm
; hw8_2.asm ; D. Thiebaut global f1 global f2 global f3 ;;; ------------------------------------------------------ ;;; f1( s ): modifies s in place and make it uppercase. f1: push ebp mov ebp, esp push ebx mov ebx, dword[ebp+8] .for: cmp byte[ebx], 0 je .done cmp byte[ebx],'a' jl .endfor cmp byte[ebx],'z' jg .endfor add byte[ebx],'A'-'a' .endfor: inc ebx jmp .for .done: pop ebx pop ebp ret 4 ;;; ------------------------------------------------------ ;;; f2( a, b, c ) ;;; returns 2a + 3b -c in eax ;;; computes it as 2(a+b) + b - c (fewer operations) f2: push ebp mov ebp, esp mov eax, dword[ebp+8+4+4] ; get first param add eax, dword[ebp+8+4] ; eax <- a+b add eax, eax ; eax <- 2(a+b) add eax, dword[ebp+8+4] ; eax <- 2(a+b) + b sub eax, dword[ebp+8] ; eax <- 2a + 3b -c pop ebp ; ret 4*3 ; return and get rid of 3 ints ;;; ------------------------------------------------------ ;;; f3( array, n ) ;;; computes the number of even ints in array, of length n. ;;; returns this number in eax. f3: push ebp mov ebp, esp ;;; push ebx push ecx mov ebx, dword[ebp+8+4] ; ebx <- array mov ecx, dword[ebp+8] ; ecx <- n mov eax, 0 ; number of even ints .for: and dword[ebx], 1 ; and array[i] with 1 jnz .notEven ; if result is 1, then odd number .even: inc eax ; otherwise, add 1 to counter. .notEven: add ebx, 4 loop .for ;;; pop ecx pop ebx pop ebp ret 2*4
Homework 9: funcs.c
#include <stdio.h> #include <stdlib.h> #include <string.h> // getMax: returns the largest of 3 integers passed // by value int getMin( int a, int b, int c ) { if ( a <= b && a <= c ) return a; if ( b <= a && b <= c ) return b; return c; } // zap: given a string haystack, and a string needle, // looks for the firlst location of needle in the haystack, and // when it finds it, replaces it with dashes. Example // char s1[] = "Mississippi"; // char s2[] = "ss"; // char *p = s1, *q = s2; // zap( s1, s2 ) will replace s1 with "Mi--issippi". // zap( s1, "mm" ) will leave s1 unchanged. // Returns 0 if zap couldn't fine the needle in // the haystack. Returns 1 if some character replacement // took place. int zap( char *haystack, char *needle ) { char *p = strstr( haystack, needle ); char *q; if ( p==NULL ) return 0; for ( q=p; q != p+strlen( needle ); q++ ) *q = '-'; return 1; } // merge(): takes two sorted arrays of ints of length 5 // and merges them into an array of length 10, so that // the third array is sorted, in increasing order. void merge( int A[], int B[], int C[] ) { int i = 0; int j = 0; int k = 0; while ( 1 ) { if ( A[i] < B[j] ) { C[k++] = A[i++]; //printf( "A[%d] (%d) < B[%d] (%d) ==> C[%d] (%d)\n", i-1, A[i-1], j, B[j], k-1, C[k-1] ); } else { C[k++] = B[j++]; //printf( "A[%d] (%d) > B[%d] (%d) ==> C[%d] (%d)\n", i, A[i], j-1, B[j-1], k-1, C[k-1] ); } if ( i>=5 || j>=5 ) break; } while ( i<5 && k <10 ) { C[k++] = A[i++]; //printf( "C[%d] (%d) <-- A[%d] (%d)\n", k-1, C[k-1], i-1, A[i-1] ); } while ( j<5 && k <10 ) { C[k++] = B[j++]; //printf( "C[%d] (%d) <-- B[%d] (%d)\n", k-1, C[k-1], j-1, B[j-1] ); } }
Homework 9: hanoi.asm
;;; hanoi.asm ;;; D. Thiebaut ;;; ;;; This program solves the "Towers of Hanoi" program ;;; in assembly. It prompts the user for an integer ;;; number of disks (must be larger than 0) and displays ;;; the name of the peg from which to move a disk, and ;;; the name of the peg to move it to. The pegs are ;;; labeled 'A', 'B', and 'C', and the disks are always ;;; assumed to moved originally from 'A' to 'B'. ;;; To assemble, link, and run: ;;; nasm -f elf 231Lib.o ;;; nasm -f elf hanoi.asm ;;; ld -melf_i386 -o hanoi hanoi.o 231Lib.o ;;; ./hanoi ;;; section .data N dd 5 section .text extern _getInput extern _println extern _printString extern _atoi global _start _start: ;;; get N from command line ;;; When any assembly language program starts, the operating system ;;; passes it argc and argv through the statck. The esp register ;;; points to argc. at esp+4, is a pointer to the beginning of argv[0], ;;; as a string. At esp+8 is a pointer to the beginning of argv[1], ;;; as a string. mov ebp, esp mov eax, dword[ebp] ; put argc into eax ;;; call _printDec ; print it ;;; call _println mov eax, dword[ebp+4+4] ; make eax points to arv[1] call _atoi ; convert ascii string to int mov dword[N], eax ; save N ;;; define the 3 pegs and pass them in bl, cl, and dl. mov bl, 'A' mov cl, 'B' mov dl, 'C' ;;; moveDisks( N, 'A', 'B', 'C' ) ; eax <- N call moveDisks ; bl <- 'A' ; cl <- 'B' ; dl <- 'C' ;;; exit mov ebx, 0 mov eax, 1 int 0x80 ;;; ------------------------------------------------------------------ ;;; moveDisks( n, source, dest, extra ) ;;; eax bl cl dl ;;; Moves the n disks from source to dest using extra if necessary. ;;; Uses recursion to move the N-1 disks above the last one. ;;; Does not modify any of the registers ;;; ------------------------------------------------------------------ moveDisks: pushad ;;; if n==1: ;;; print( source, dest ) cmp eax, 1 jg recurse mov al, bl ; print source call printChar mov al, ' ' ; print space call printChar mov al, cl ; print dest call printChar call _println ; print \n popad ; done! return ret recurse: ;;; moveDisks( n-1, source, temp, dest ) dec eax ; eax <- n-1 xchg cl, dl ; swap cl & dl call moveDisks ; move n-1 xchg cl, dl ; swap them back ;;; print( source, dest ) mov al, bl ; print source call printChar mov al, ' ' ; print space call printChar mov al, cl ; print dest call printChar call _println ; print \n ;;; moveDisks( n-1, temp, dest, source ) popad ; get all the original parameters back pushad ; and push them back in the stack xchg bl, dl ; exchange source and temp dec eax ; eax <-- n-1 call moveDisks ; recurse popad ; pop all registers back ret ;;; ------------------------------------------------------------------ ;;; printChar: prints the character in al ;;; does not modify any other register ;;; ------------------------------------------------------------------ section .data char db 'A' section .text printChar: pushad mov byte[char],al mov ecx, char mov edx, 1 call _printString popad ret