CSC231 List of All Class Demo Files 2012
--D. Thiebaut 07:58, 26 November 2012 (EST)
Updated --D. Thiebaut 10:09, 14 December 2012 (EST)
Contents
- 1 Listings from ~231a/handout
- 1.1 Scripts
- 1.2 Asm Files
- 1.2.1 asm_io.asm
- 1.2.2 asm_io.inc
- 1.2.3 buggy1.asm
- 1.2.4 dddTutorial.asm
- 1.2.5 deleteme.asm
- 1.2.6 dummy.asm
- 1.2.7 dumpRegs.asm
- 1.2.8 dumpRegs.inc
- 1.2.9 exoFlags.asm
- 1.2.10 factorial.asm
- 1.2.11 fibonacci.asm
- 1.2.12 fibWithLoop2.asm
- 1.2.13 fibWithLoop3.asm
- 1.2.14 fibWithLoop.asm
- 1.2.15 float1.asm
- 1.2.16 funcExample2.asm
- 1.2.17 funcExample3.asm
- 1.2.18 funcExample.asm
- 1.2.19 hanoi1.asm
- 1.2.20 hanoi2.asm
- 1.2.21 hello2.asm
- 1.2.22 hello3.asm
- 1.2.23 hello.asm
- 1.2.24 helloMovsb.asm
- 1.2.25 howMuchStack2.asm
- 1.2.26 howMuchStack.asm
- 1.2.27 hw12_maze.asm
- 1.2.28 hw12_play.asm
- 1.2.29 hw12_sol.asm
- 1.2.30 hw3b.asm
- 1.2.31 hw3c.asm
- 1.2.32 hw8asol2.asm
- 1.2.33 hw8asol.asm
- 1.2.34 hw9a.asm
- 1.2.35 hw9.asm
- 1.2.36 hwtest.asm
- 1.2.37 lab1.asm
- 1.2.38 loop1.asm
- 1.2.39 loop2.asm
- 1.2.40 loop3.asm
- 1.2.41 loop4.asm
- 1.2.42 loopDemo.asm
- 1.2.43 loopExample.asm
- 1.2.44 manymoves.asm
- 1.2.45 mickeyMouse.asm
- 1.2.46 midTerm.asm
- 1.2.47 minilab1.asm
- 1.2.48 minilab1_v1.asm
- 1.2.49 minilab1_v2.asm
- 1.2.50 movStrings1.asm
- 1.2.51 movStrings2.asm
- 1.2.52 movStrings3.asm
- 1.2.53 movStrings4.asm
- 1.2.54 printBinary.asm
- 1.2.55 printInteger.asm
- 1.2.56 printStars2.asm
- 1.2.57 printStars.asm
- 1.2.58 recursFib2.asm
- 1.2.59 recursFib.asm
- 1.2.60 reviewSumTwoVars.asm
- 1.2.61 simpleAdd.asm
- 1.2.62 skel2.asm
- 1.2.63 skel.asm
- 1.2.64 sumFloat1.asm
- 1.2.65 sumFloat2.asm
- 1.2.66 sumFloat3.asm
- 1.2.67 sumFloat4.asm
- 1.2.68 sumFloat5.asm
- 1.2.69 topDown1.asm
- 1.2.70 topDown2.asm
- 1.2.71 topDown3.asm
- 1.2.72 topDown4.asm
- 1.2.73 topDown5.asm
- 1.2.74 topDown6.asm
- 1.2.75 topDown7.asm
- 1.2.76 topDown.asm
- 1.2.77 topDown_v1.asm
- 1.2.78 topDown_v2.asm
- 1.2.79 topDown_v3.asm
- 1.2.80 topDown_v4.asm
- 1.2.81 topDown_v5.asm
- 1.2.82 topDown_v6.asm
- 1.2.83 topDown_v7.asm
- 1.3 C/C++/Java Files
- 1.4 Python Files
- 2 Script to Generate This List
Listings from ~231a/handout
Scripts
nasmld
#! /bin/bash
set -e # exit on error
filename=$(basename "$1")
extension="${filename##*.}"
filename="${filename%.*}"
nasm -f elf -F stabs $filename.asm
ld -o $filename -melf_i386 $filename.o
Asm Files
asm_io.asm
;
; file: asm_io.asm
; Assembly I/O routines
; To assemble for DJGPP
; nasm -f coff -d COFF_TYPE asm_io.asm
; To assemble for Borland C++ 5.x
; nasm -f obj -d OBJ_TYPE asm_io.asm
; To assemble for Microsoft Visual Studio
; nasm -f win32 -d COFF_TYPE asm_io.asm
; To assemble for Linux
; nasm -f elf -d ELF_TYPE asm_io.asm
%define NL 10
%define CF_MASK 00000001h
%define PF_MASK 00000004h
%define AF_MASK 00000010h
%define ZF_MASK 00000040h
%define SF_MASK 00000080h
%define DF_MASK 00000400h
%define OF_MASK 00000800h
;
; Linux C doesn't put underscores on labels
;
;;; %ifdef ELF_TYPE
%define _scanf scanf
%define _printf printf
%define _getchar getchar
%define _putchar putchar
%define _fputs fputs
;;; %endif
%ifdef OBJ_TYPE
segment .data public align=4 class=data use32
%else
segment .data
%endif
int_format db "%i", 0
string_format db "%s", 0
reg_format db "Register Dump # %d", NL
db "EAX = %.8X EBX = %.8X ECX = %.8X EDX = %.8X", NL
db "ESI = %.8X EDI = %.8X EBP = %.8X ESP = %.8X", NL
db "EIP = %.8X FLAGS = %.4X %s %s %s %s %s %s %s", NL
db 0
carry_flag db "CF", 0
zero_flag db "ZF", 0
sign_flag db "SF", 0
parity_flag db "PF", 0
overflow_flag db "OF", 0
dir_flag db "DF", 0
aux_carry_flag db "AF", 0
unset_flag db " ", 0
mem_format1 db "Memory Dump # %d Address = %.8X", NL, 0
mem_format2 db "%.8X ", 0
mem_format3 db "%.2X ", 0
stack_format db "Stack Dump # %d", NL
db "EBP = %.8X ESP = %.8X", NL, 0
stack_line_format db "%+4d %.8X %.8X", NL, 0
math_format1 db "Math Coprocessor Dump # %d Control Word = %.4X"
db " Status Word = %.4X", NL, 0
valid_st_format db "ST%d: %.10g", NL, 0
invalid_st_format db "ST%d: Invalid ST", NL, 0
empty_st_format db "ST%d: Empty", NL, 0
;
; code is put in the _TEXT segment
;
%ifdef OBJ_TYPE
segment text public align=1 class=code use32
%else
segment .text
%endif
global read_int, print_int, print_string, read_char, print_hex
global print_char, print_nl, sub_dump_regs, sub_dump_mem
global sub_dump_math, sub_dump_stack
extern _scanf, _printf, _getchar, _putchar, _fputs
read_int:
enter 4,0
pusha
pushf
lea eax, [ebp-4]
push eax
push dword int_format
call _scanf
pop ecx
pop ecx
popf
popa
mov eax, [ebp-4]
leave
ret
print_int:
enter 0,0
pusha
pushf
push eax
push dword int_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
print_hex:
enter 0,0
pusha
pushf
push eax
push dword mem_format2
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
print_string:
enter 0,0
pusha
pushf
push eax
push dword string_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
read_char:
enter 4,0
pusha
pushf
call _getchar
mov [ebp-4], eax
popf
popa
mov eax, [ebp-4]
leave
ret
print_char:
enter 0,0
pusha
pushf
push eax
call _putchar
pop ecx
popf
popa
leave
ret
print_nl:
enter 0,0
pusha
pushf
push dword 10 ; 10 == ASCII code for \n
call _putchar
pop ecx
popf
popa
leave
ret
sub_dump_regs:
enter 4,0
pusha
pushf
mov eax, [esp] ; read FLAGS back off stack
mov [ebp-4], eax ; save flags
;
; show which FLAGS are set
;
test eax, CF_MASK
jz cf_off
mov eax, carry_flag
jmp short push_cf
cf_off:
mov eax, unset_flag
push_cf:
push eax
test dword [ebp-4], PF_MASK
jz pf_off
mov eax, parity_flag
jmp short push_pf
pf_off:
mov eax, unset_flag
push_pf:
push eax
test dword [ebp-4], AF_MASK
jz af_off
mov eax, aux_carry_flag
jmp short push_af
af_off:
mov eax, unset_flag
push_af:
push eax
test dword [ebp-4], ZF_MASK
jz zf_off
mov eax, zero_flag
jmp short push_zf
zf_off:
mov eax, unset_flag
push_zf:
push eax
test dword [ebp-4], SF_MASK
jz sf_off
mov eax, sign_flag
jmp short push_sf
sf_off:
mov eax, unset_flag
push_sf:
push eax
test dword [ebp-4], DF_MASK
jz df_off
mov eax, dir_flag
jmp short push_df
df_off:
mov eax, unset_flag
push_df:
push eax
test dword [ebp-4], OF_MASK
jz of_off
mov eax, overflow_flag
jmp short push_of
of_off:
mov eax, unset_flag
push_of:
push eax
push dword [ebp-4] ; FLAGS
mov eax, [ebp+4]
sub eax, 10 ; EIP on stack is 10 bytes ahead of orig
push eax ; EIP
lea eax, [ebp+12]
push eax ; original ESP
push dword [ebp] ; original EBP
push edi
push esi
push edx
push ecx
push ebx
push dword [ebp-8] ; original EAX
push dword [ebp+8] ; # of dump
push dword reg_format
call _printf
add esp, 76
popf
popa
leave
ret 4
sub_dump_stack:
enter 0,0
pusha
pushf
lea eax, [ebp+20]
push eax ; original ESP
push dword [ebp] ; original EBP
push dword [ebp+8] ; # of dump
push dword stack_format
call _printf
add esp, 16
mov ebx, [ebp] ; ebx = original ebp
mov eax, [ebp+16] ; eax = # dwords above ebp
shl eax, 2 ; eax *= 4
add ebx, eax ; ebx = & highest dword in stack to display
mov edx, [ebp+16]
mov ecx, edx
add ecx, [ebp+12]
inc ecx ; ecx = # of dwords to display
stack_line_loop:
push edx
push ecx ; save ecx & edx
push dword [ebx] ; value on stack
push ebx ; address of value on stack
mov eax, edx
sal eax, 2 ; eax = 4*edx
push eax ; offset from ebp
push dword stack_line_format
call _printf
add esp, 16
pop ecx
pop edx
sub ebx, 4
dec edx
loop stack_line_loop
popf
popa
leave
ret 12
sub_dump_mem:
enter 0,0
pusha
pushf
push dword [ebp+12]
push dword [ebp+16]
push dword mem_format1
call _printf
add esp, 12
mov esi, [ebp+12] ; address
and esi, 0FFFFFFF0h ; move to start of paragraph
mov ecx, [ebp+8]
inc ecx
mem_outer_loop:
push ecx
push esi
push dword mem_format2
call _printf
add esp, 8
xor ebx, ebx
mem_hex_loop:
xor eax, eax
mov al, [esi + ebx]
push eax
push dword mem_format3
call _printf
add esp, 8
inc ebx
cmp ebx, 16
jl mem_hex_loop
mov eax, '"'
call print_char
xor ebx, ebx
mem_char_loop:
xor eax, eax
mov al, [esi+ebx]
cmp al, 32
jl non_printable
cmp al, 126
jg non_printable
jmp short mem_char_loop_continue
non_printable:
mov eax, '?'
mem_char_loop_continue:
call print_char
inc ebx
cmp ebx, 16
jl mem_char_loop
mov eax, '"'
call print_char
call print_nl
add esi, 16
pop ecx
loop mem_outer_loop
popf
popa
leave
ret 12
; function sub_dump_math
; prints out state of math coprocessor without modifying the coprocessor
; or regular processor state
; Parameters:
; dump number - dword at [ebp+8]
; Local variables:
; ebp-108 start of fsave buffer
; ebp-116 temp double
; Notes: This procedure uses the Pascal convention.
; fsave buffer structure:
; ebp-108 control word
; ebp-104 status word
; ebp-100 tag word
; ebp-80 ST0
; ebp-70 ST1
; ebp-60 ST2 ...
; ebp-10 ST7
;
sub_dump_math:
enter 116,0
pusha
pushf
fsave [ebp-108] ; save coprocessor state to memory
mov eax, [ebp-104] ; status word
and eax, 0FFFFh
push eax
mov eax, [ebp-108] ; control word
and eax, 0FFFFh
push eax
push dword [ebp+8]
push dword math_format1
call _printf
add esp, 16
;
; rotate tag word so that tags in same order as numbers are
; in the stack
;
mov cx, [ebp-104] ; ax = status word
shr cx, 11
and cx, 7 ; cl = physical state of number on stack top
mov bx, [ebp-100] ; bx = tag word
shl cl,1 ; cl *= 2
ror bx, cl ; move top of stack tag to lowest bits
mov edi, 0 ; edi = stack number of number
lea esi, [ebp-80] ; esi = address of ST0
mov ecx, 8 ; ecx = loop counter
tag_loop:
push ecx
mov ax, 3
and ax, bx ; ax = current tag
or ax, ax ; 00 -> valid number
je valid_st
cmp ax, 1 ; 01 -> zero
je zero_st
cmp ax, 2 ; 10 -> invalid number
je invalid_st
push edi ; 11 -> empty
push dword empty_st_format
call _printf
add esp, 8
jmp short cont_tag_loop
zero_st:
fldz
jmp short print_real
valid_st:
fld tword [esi]
print_real:
fstp qword [ebp-116]
push dword [ebp-112]
push dword [ebp-116]
push edi
push dword valid_st_format
call _printf
add esp, 16
jmp short cont_tag_loop
invalid_st:
push edi
push dword invalid_st_format
call _printf
add esp, 8
cont_tag_loop:
ror bx, 2 ; mov next tag into lowest bits
inc edi
add esi, 10 ; mov to next number on stack
pop ecx
loop tag_loop
frstor [ebp-108] ; restore coprocessor state
popf
popa
leave
ret 4
asm_io.inc
extern read_int, print_int, print_string, print_hex
extern read_char, print_char, print_nl
extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack
%macro dump_regs 1
push dword %1
call sub_dump_regs
%endmacro
;
; usage: dump_mem label, start-address, # paragraphs
%macro dump_mem 3
push dword %1
push dword %2
push dword %3
call sub_dump_mem
%endmacro
%macro dump_math 1
push dword %1
call sub_dump_math
%endmacro
%macro dump_stack 3
push dword %3
push dword %2
push dword %1
call sub_dump_stack
%endmacro
buggy1.asm
section .data
hexChars: db "0123456789ABCDEF"
section .text
gobal _start
_start:
mov al,0xf5
and al,0x0f ;al <-- 05
mov ebx, hexChars ;ebx <-- address hexChars
add bl, al ;ebx <-- hexChars+05
mov al,[ebx] ;al <-- '5'
call printChar
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;;----------------------------------------------------
;;; printChar: prints char in al to screen
;;;----------------------------------------------------
section .data
pc_temp: db 0
section .text
printChar: pushad
mov [pc_temp],al ;store char in string
mov eax, 4 ;print string
mov ebx, 1
mov ecx, pc_temp
mov edx, 1
int 0x80
popad
ret
dddTutorial.asm
;;; dddTutorial.asm
;;; YourName
;;;
;;; this program should be assembled, linked, and debugged
;;; with ddd to figure out the contents of msg1 at the different
;;; phases of the program: phase1, phase2, phase3, phase4,
;;; and phase5
;;;
;;; to assemble and run:
;;;
;;; nasm -f elf -F stabs dddTutorial.asm
;;; ld -melf_i386 -o dddTutorial dddTutorial.o
;;; ./dddTutorial
;;; -------------------------------------------------------------------
EXIT equ 1
WRITE equ 4
STDOUT equ 1
;; ------------------------------------------------------------
;; data areas
;; ------------------------------------------------------------
section .data
msg0 db 10, 10, 10, 10, 10
msg1 db " "
db 10, 10, 10, 10, 10
MSGLEN equ $-msg0
;; ------------------------------------------------------------
;; code area
;; ------------------------------------------------------------
section .text
global _start
_start:
nop
nop
nop
phase1:
mov eax, 0x6c6c6468
mov ebx, 0x6064216e
mov ecx, 0x6c687400
mov edx, 0x13070e09
phase2:
mov dword [msg1], eax
mov dword [msg1+4], ebx
mov dword [msg1+8], ecx
mov dword [msg1+12], edx
phase3: or dword [msg1], 256
xor dword [msg1+4], 0x01010101
or dword [msg1+8], 'r'
phase4:
or word [msg1+12], 0x6060
or word [msg1+14], 0x6060
phase5:
mov eax, WRITE
mov ebx, STDOUT
mov ecx, msg0
mov edx, MSGLEN
int 0x80
;; exit()
mov eax,EXIT
mov ebx, 0
int 0x80 ; final system call
deleteme.asm
_start:
mov ebx, Pascal ;pass address of array in ebx
call init ;store 0 in Pascal array
;and 1 in first cell
mov ecx, 10
for: mov ebx, Pascal ;pass address of array in ebx
call printArray ;print Pascal array
mov ebx, Pascal ;pass address of array
call nextLine ;compute next line of triangle
loop for ;
;;; exit
mov eax, 1
mov ebx, 0
int 0x80
mov eax, 0x01234567
mov ebx, 0x89ABCDEF
xor ecx, ecx
push ax
pop cx
push ax
push bx
pop ecx
call next
next: pop ecx
dummy.asm
# this
# is
# it
dumpRegs.asm
;;; ---------------------------------------------------------
;;; dumpRegs.asm
;;; D. Thiebaut
;;; 11/13/12
;;; This libary supports several functions that allow the user
;;; to dump the contents of the main 6 registers (eax, ebx, ecx,
;;; edx, esi and edi) to the screen. Great for debugging without
;;; a debugger.
;;;
;;; Typical output:
;;; +-----------------+
;;; | eax = 1234 5678 |
;;; | ebx = 55FF 55FF |
;;; | ecx = FEDC BA98 |
;;; | edx = 0000 0000 |
;;; | esi = 1111 2222 |
;;; | edi = 2222 3333 |
;;; +-----------------+
;;; Include in program as follows:
;;;
;;;
;;; %include "dumpRegs.asm"
;;; ---------------------------------------------------------
section .data
hex db "0123456789ABCDEF"
regs db "axbxcxdxsidi"
line db "+-----------------+", 10
string db "| exx = .... .... |", 10
lineLen equ $-string
reg equ string+3
word1 equ string+8
section .text
;;; ---------------------------------------------------------
;;; dumpRegs: dumps the contents of the 6 main registers (eax
;;; ebx, ecx, edx, esi and edi) in a box on the screen.
;;; the screen. Does not modify any register
;;; ---------------------------------------------------------
dumpRegs: pushad
;;; put all the registers to print in the stack. The loop
;;; will pop each one, one at a time, once per loop.
push edi
push esi
push edx
push ecx
push ebx
push eax
;;; print top bar
call printBar
;;; prepare to loop 6 times (6 registers )
mov ecx, 6
mov esi, 0
.for pop ebx ;get value of register to convert from stack
push ecx ;save loop counter
lea eax, [regs + esi*2] ;get address of string representing register
mov ax, word [eax] ;ax gets "ax" or "bx" or "cx" or ... "di"
mov word[reg], ax ;modify string with name of register
mov edx, word1 ;edx points to buffer where to store hex digits
;ebx contains register to convert
call storeDWord ;store hex equivalent of ebx in string
mov ecx, string ;print the whole string
mov edx, lineLen
call printInt80
inc esi ;index into register names incremented
pop ecx ;get loop counter back
loop .for
;;; print bottom bar
call printBar
popad
ret
;;; ---------------------------------------------------------
;;; storeDWord: gets
;;; ebx: register to convert
;;; edx: address where to put information
;;; ---------------------------------------------------------
storeDWord: rol ebx, 16 ;bring most sig word in least sig word
call storeWord
inc edx ;make edx skip space in string
rol ebx, 16 ;get lower byte back in least sig pos
call storeWord
ret
;;; ---------------------------------------------------------
;;; storeWord: gets
;;; bx: word to convert
;;; edx: address where to put information. edx incremented by 4
;;; ---------------------------------------------------------
storeWord: rol bx, 8 ;put most sig byte of bx in lower position
call storeByte ;and convert it. Store it in where edx
;points to.
rol bx, 8 ;same with lower nybble
call storeByte
ret
;;; ---------------------------------------------------------
;;; storeByte: gets
;;; bl: byte to convert
;;; edx: address where to store information. edx incremented by 2 automatically
;;; ---------------------------------------------------------
storeByte: push ebx
push eax
rol bl, 4 ;get upper nybble in lower position (LSB)
mov al, bl ;play with al now
and eax, 0x0000000F ;clear all but the least significant nybble
add eax, hex ;get ascii in hex array equivalentn to nybble
mov al, [eax] ;hex digit now in bl
mov byte [edx], al ;store ascii in string
inc edx
rol bl, 4 ;get lower nybble back
mov al, bl ;play with al
and eax, 0x0000000F
add eax, hex
mov al, [eax]
mov byte [edx], al
inc edx
pop eax
pop ebx
ret
;;; ---------------------------------------------------------
;;; printInt80: prints on the screen the string whose address
;;; is in ecx and length in edx.
;;; does not modify registers
;;; ---------------------------------------------------------
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; ---------------------------------------------------------
;;; printBar: prints the horizontal bar
;;; does not modify registers
;;; ---------------------------------------------------------
printBar: push ecx
push edx
mov ecx, line
mov edx, lineLen
call printInt80
pop edx
pop ecx
ret
dumpRegs.inc
;;; dumpRegs.inc
section .data
regNames db "| eax = ", "| ebx = ",
db "| ecx = ", "| edx = ",
db "| edi = ", "| esi = "
;;; holds the line for the top and bottom of the box
line db "+------------------+", 10
lineLen equ $-line
;;; holds a space
space db " "
spaceLen equ $-space
;;; holds the formatted bar used at the end of a line
bar db " |", 10
barLen equ $-bar
;;; a string of all the hex digits
hexChars db "0123456789ABCDEF"
;;; holds the value of the current register we're printing
currentReg dd 0x00000000
;;; used to print the appropriate label
counter dw 0
section .text
;;; dumpRegs()
;;; no parameters
;;; prints the contents of the following registers:
;;; eax, ebx, ecx, edx, esi, edi
;;; inside of a nicely formatted box.
dumpRegs: mov word[counter], 0
call printLine ;prints the top of the box
mov dword[currentReg], eax ;print eax's formatted line
call printReg
mov dword[currentReg], ebx ;print ebx's formatted line
call printReg
mov dword[currentReg], ecx ;print ecx's formatted line
call printReg
mov dword[currentReg], edx ;print edx's formatted line
call printReg
mov dword[currentReg], edi ;print edi's formatted line
call printReg
mov dword[currentReg], esi ;print esi's formatted line
call printReg
call printLine ;print the bottom of the box
;exit dumpRegs()
ret
;;; printLine():
;;; no parameters
;;; no modifications
;;; prints "+------------------+" on the screen and
;;; returns to a new line. Uses int 0x80 to print.
;;;
printLine:
push ecx ;store registers
push edx
mov ecx, line ;the line to print
mov edx, lineLen ;the length of that line
call printString
;;; restore the values of eax, ebx, ecx, and edx
pop edx
pop ecx
;;; exit printLine()
ret
;;; printString(String string, int lengthOfString):
;;; parameters:
;;; ecx = string to print
;;; edx = length of the string to print
;;; modifies: ecx, edx
;;; prints the string passed in through ecx
;;; using int 0x80.
;;;
printString:
push eax ;save eax
push ebx ;save ebx
mov eax, 4 ;write
mov ebx, 1 ;stdout
int 0x80 ;print the string
pop ebx ;restore original contents of ebx
pop eax ;restore original contents of eax
;;; exit printString()
ret
;;; printSpace():
;;; no parameters
;;; no modifications
;;; prints a space by calling printString().
;;;
printSpace: push edx ;save edx
push ecx ;save ecx
mov ecx, space ;move a space
;into ecx (parameter
;for printString())
mov edx, spaceLen ;move the length
;of that space
;into edx (parameter
;for printString())
call printString
pop ecx ;restore original
;value of ecx
pop edx ;restore original
; value of edx
;exit printSpace()
ret
;;; printLabel():
;;; no parameters
;;; no modifications
;;; prints the first part of each line
;;; by calling printString().
;;;
;;; i.e.:
;;; | eax =
;;;
printLabel: push ecx ;save ecx
push edx ;save edx
mov ecx, regNames ;the list of register names
;(parameter for printString())
add cx, word[counter] ;the index of the name of
;the register we're on
mov edx, 8 ;the length of each label
;(parameter for printString())
call printString
pop edx ;restore original edx
pop ecx ;restore original ecx
;exit printLabel()
ret
;;; printEndBar():
;;; no parameters
;;; no modifications
;;; prints " |" (after a register has
;;; been printed out) by calling printString()
;;;
printEndBar: push edx ;save edx
push ecx ;save ecx
mov ecx, bar ;move the string with the bar
;(parameter for printString())
mov edx, barLen ;the length of the bar string
;(parameter for printString())
call printString
pop ecx ;restore original ecx
pop edx ;restore original edx
;exit printEndBar()
ret
;;; printReg(int currentReg)
;;; parameters: currentReg (contains the contents of the current
;;; register that we're printing)
;;; no modifications
;;;
;;; calls printLabel, printHexWord, printSpace, printHexByte, and
;;; printEndBar to print out the contents of the given register
;;; in blocks like:
;;;
;;; | eax = 0000 00 00 |
;;;
printReg: call printLabel ;print the register label
call printHexWord ;print the first four hex
;digits
call printSpace
call printHexByte ;print the fifth and sixth
;hex digits
call printSpace
call printHexByte ;print the last two hex digits
call printEndBar ;print the end of the box (" |")
add word[counter], 8 ;increment the counter for
;label by 8, because each
;label is 8 bytes long
; exit printReg()
ret
;;; printHexDigit(int currentReg)
;;; parameters: currentReg (holds the value of the current
;;; register that we're printing)
;;; no modifications
;;; prints a hexdigit (=4 bits) using the int 0x80 method
;;;
printHexDigit:
;save each register, as all would be altered by the int 0x80 call
push edx
push ecx
push ebx
push eax
;move the contents of the register we're printing (stored in currentReg)
;into eax
mov eax, dword[currentReg]
rol eax, 4 ;move the next digit to
;print into al (digits
;are 4 bits long)
mov dword[currentReg], eax ;save the changes made
and eax, 0x0F ;isolate al
; move hexChars into ecx and use al as an index so that we can
; print the letter/number corresponding to the current digit
mov ecx, hexChars
add ecx, eax
mov eax, 4 ;write
mov ebx, 1 ;stdout
mov edx, 1 ;print 1 character
;that is 1 byte long
int 0x80 ;print the character
;restore the registers to their original values
pop eax
pop ebx
pop ecx
pop edx
;exit printHexDigit()
ret
;;; printHexByte():
;;; parameters: currentReg (holds the value of the current
;;; register that we're printing)
;;; no modifications
;;; calls printHexDigit() twice to print out
;;; the hex value of a byte.
;;;
printHexByte: call printHexDigit
call printHexDigit
;;; exit printHexByte()
ret
;;; printHexWord():
;;; parameters: currentReg (holds the value of the current
;;; register that we're printing)
;;; no modifications
;;; calls printHexByte() twice to print out
;;; the hex value of a word (2 bytes long)
printHexWord: call printHexByte
call printHexByte
;;; exit printHexWord()
ret
exoFlags.asm
;;; -------------------------------------------------------------------
;;; flagbits.asm
;;; D. Thiebaut
;;;
;;; a program with several compare instructions and the resulting
;;; flags generated by the ALU.
;;; This program was debugged by ddd and the flags resulting from
;;; the execution of each instruction was then added as a comment
;;; on the same line as the instruction.
;;; The flags are
;;; CF: carry
;;; PF: parity (1 if the number of 1s in the result is even)
;;; AF: auxiliary carry (carry into the MSB)
;;; SF: sign (1 if result is negative, 0 otherwise)
;;; ZF: zero (1 if result is 0, 1 otherwise)
;;; IF: interrupt flag (used for critical sections)
;;; OF: overflow (1 if the result overflowed assuming signed numbers)
;;; ID: direction bit (for string operations)
;;; -------------------------------------------------------------------
EXIT equ 1
;; ------------------------------------------------------------
;; data areas
;; ------------------------------------------------------------
section .data
;; ------------------------------------------------------------
;; code area
;; ------------------------------------------------------------
section .text
global _start
_start: nop
nop ; immediate Flag values
; value AFTER the instruction
;----------- ----------------------
mov al, 0x43 ; 67
cmp al, 0x43 ; PF ZF IF ID
cmp al, 0x42 ; 66 IF ID
cmp al, 0x44 ; 68 CF PF AF SF IF ID
cmp al, 0xff ; 255 or -1 CF PF AF IF ID
cmp al, 0x81 ; 129 or -127 CF SF IF OF ID
mov al, 0xfe ; 254, or -2
cmp al, 0xff ; 255 or -1 CF PF AF SF IF ID
cmp al, 0xfd ; 253 or -3 IF ID
cmp al, 0x81 ; 129 or -127 PF IF ID
cmp al, 0x7f ; 127 AF IF OF ID
;; exit()
mov eax,EXIT
mov ebx,0
int 0x80 ; final system call
factorial.asm
;;; factorial.asm
;;;
;;; demo of the recursive factorial program
;;; uses the stack to pass parameters.
%include "dumpRegs.asm"
section .data
n dd 5 ;n
factN dd 0 ;we'll put n! here
section .text
global _start
_start: push eax ;make room in stack for resut
push dword[n] ;pass n
call fact
pop eax ;put result in eax
mov dword[factN],eax ;and in global
call dumpRegs
;;; exit
mov eax, 1
mov ebx, 0
int 0x80
;;; --------------------------------------------------------
;;; fact: computes the factorial of n, where n is passed in
;;; eax. Returns the result in edx
;;; --------------------------------------------------------
fact: push ebp
mov ebp, esp
pushad
mov eax, [ebp+8] ;get n
cmp eax, 1
jne .recurse
mov dword[ebp+12], 1 ;set result to 1
popad
pop ebx
ret 1*4 ;get rid of n param
.recurse:
dec eax
push eax ;make room for result
push eax ;pass n-1
call fact
pop eax ;get fact(n-1)
mul dword[ebp+8] ;mult by n
mov dword[ebp+12],eax
;pass result back
popad
pop ebp
ret 1*4
fibonacci.asm
;;; fibonacci.asm
;;; D. Thiebaut
;;; simple program computing the first 5 fibonacci terms without
;;; using a loop.
;;; Each term is stored in a double word.
;;;
section .data
fib dd 0, 0, 0, 0, 0
section .text
global _start
_start:
mov dword[fib], 1 ; fib[0] <- 1
mov dword[fib+4], 1 ; fib[1] <- 1
mov eax, dword[fib] ; eax <- fib[0]
add eax, dword[fib+4] ; eax <- fib[0]+fib[1]
mov dword[fib+8], eax ; fib[2] <- eax
add eax, dword[fib+4] ; eax <- fib[2] + fib[1]
mov dword[fib+12], eax ; fib[3] <- eax
add eax, dword[fib+8] ; eax <- fib[3] + fib[2]
mov dword[fib+16], eax ; fib[4] <- eax
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
fibWithLoop2.asm
;;; fibWithLoop2.asm
;;; D. T.
;;; a simple demo program computing a few Fibonacci terms
;;; using indirect addressing modes and loops
;;; To compile and run
;;; nasm -f elf fibWithLoop2.asm
;;; nasm -f elf asm_io.asm
;;; gcc -m32 -o fibWithLoop2 driver.c fibWithLoop2.o asm_io.o
;;; ./fibWithLoop2
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
Fib db 0,0,0,0,0,0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ebx, 0 ; make ebx point to array
mov ecx, 5 ; # of terms to compute
mov eax, 1 ; first term as double word (for printing)
mov byte [Fib+ebx], al ; set 1st term
call print_int ; print it
call print_nl
mov byte [Fib+ebx+1], al ; set 2nd term
call print_int ; print it
call print_nl
sub ecx,2 ; adjust counter
add ebx,2 ; and pointer. ebx points to
; empty Fib
for: add al, byte [Fib+ebx-2] ; al<- fib(n-1)+fib(n-2)
mov byte [Fib+ebx], al ; store new term
call print_int ; print it
call print_nl
inc ebx ; point to new term
loop for ; loop back
;; return to C program
ret
fibWithLoop3.asm
;;; fibWithLoop2.asm
;;; D. T.
;;; a simple demo program computing a few Fibonacci terms
;;; using indirect addressing modes and loops
;;; To compile and run
;;; nasm -f elf fibWithLoop2.asm
;;; nasm -f elf asm_io.asm
;;; gcc -m32 -o fibWithLoop2 driver.c fibWithLoop2.o asm_io.o
;;; ./fibWithLoop2
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
msg db "How many terms do you want printed (1-20)? ", 0
Fib times(20) db 0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov eax, msg
call print_string
call read_int
mov ebx, 0 ; make ebx point to array
mov ecx, eax ; # of terms to compute
mov eax, 1 ; first term as double word (for printing)
mov byte [Fib+ebx], al ; set 1st term
call print_int ; print it
call print_nl
mov byte [Fib+ebx+1], al ; set 2nd term
call print_int ; print it
call print_nl
sub ecx,2 ; adjust counter
add ebx,2 ; and pointer. ebx points to
; empty Fib
for: add al, byte [Fib+ebx-2] ; al<- fib(n-1)+fib(n-2)
mov byte [Fib+ebx], al ; store new term
call print_int ; print it
call print_nl
inc ebx ; point to new term
loop for ; loop back
;; return to C program
ret
fibWithLoop.asm
;;; fibWithLoop.asm
;;; D. T.
;;; a simple demo program computing a few Fibonacci terms
;;; using indirect addressing modes and loops
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
Fib db 0,0,0,0,0,0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ebx, Fib ; make ebx point to array
mov ecx, 5 ; # of terms to compute
mov eax, 1 ; first term as double word (for printing)
mov byte[ebx], al ; set 1st term
call print_int ; print it
call print_nl
mov byte[ebx+1], al ; set 2nd term
call print_int ; print it
call print_nl
sub ecx,2 ; adjust counter
add ebx,2 ; and pointer. ebx points to
; empty Fib
for: add al, byte[ebx-2] ; al<- fib(n-1)+fib(n-2)
mov byte[ebx], al ; store new term
call print_int ; print it
call print_nl
inc ebx ; point to new term
loop for ; loop back
;; return to C program
ret
float1.asm
; float1.asm use "C" printf on float
;
; Assemble: nasm -f elf float1.asm
; Link: gcc -m32 -o float1 float1.o
; Run: ./float1
; prints a single precision floating point number on the screen
; This program uses the external printf C function which requires
; a format string defining what to print, and a variable number of
; variables to print.
extern printf ; the C function to be called
SECTION .data ; Data section
msg: db "flt1 = %e",0x0a,0x00
flt1: dd 5.327e-30 ; 32-bit floating point
SECTION .bss
flttmp: resq 1 ; 64-bit temporary for printing flt1
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
fld dword [flt1] ; need to convert 32-bit to 64-bit
fstp qword [flttmp] ; floating load makes 80-bit,
; store as 64-bit
push dword [flttmp+4] ; 32 bit floating point
push dword [flttmp]
push dword msg ; address of format string
call printf ; Call C function
add esp, 12 ; pop stack 10*4 bytes
mov eax, 1 ; exit code, 0=normal
mov ebx, 0
int 0x80 ;
funcExample2.asm
;;; ----------------------------------
;;; funcExample2.asm
;;; prints 2 strings with lines of stars
;;; between them
;;; ----------------------------------
section .data
Hello db "Hello "
There db "there!", 10, 10, 10
HelloLen equ $-Hello
line db "****************************", 10
lineLen equ $-line
section .text
global _start
_start:
;;; ----------------------------------
;;; main program
;;; ----------------------------------
call printLine
mov ecx, Hello
mov edx, HelloLen
call printString
call printLine
mov ecx, There
mov edx, 9
call printString
call printLine
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------
;;; printString: Prints a string whose
;;; address is in ecx and length in edx
;;; ----------------------------------
printString: mov eax, 4
mov ebx, 1
;;; int 0x80
;;; ret
;;; ----------------------------------
;;; printLine: prints a line of stars.
;;; ----------------------------------
printLine: mov ecx, line
mov edx, lineLen
call printString
ret
funcExample3.asm
;;; ----------------------------------
;;; funcExample2.asm
;;; prints 2 strings with lines of stars
;;; between them
;;; ----------------------------------
%include "dumpRegs.inc"
section .data
a dd 3
b dd 2
res dd 0
section .text
global _start
_start:
;;; ----------------------------------
;;; main program
;;; ----------------------------------
push dword[a]
push dword[b]
mov eax, res
push eax
call sum
mov eax, dword[res]
call dumpRegs
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
sum: push ebp
mov ebp, esp
push eax
push ebx
mov eax, [ebp+12]
add eax, [ebp+16]
mov ebx, [ebp+8]
mov dword [ebx], eax
pop ebx
pop eax
pop ebp
ret 3*4
funcExample.asm
;;; ------------------------------------
;;; funcExample.asm
;;; prints 2 strings using functions
;;; ------------------------------------
section .data
Hello db "Hello "
There db "there!", 10, 10, 10
HelloLen equ $-Hello
section .text
global _start
_start:
;;; ------------------------------------
;;; main program
;;; ------------------------------------
;;; print message
mov ecx, Hello
mov edx, HelloLen
call printString
mov ecx, There
mov edx, 9
call printString
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ------------------------------------
;;; printString: prints string whose
;;; address is in ecx, and length in edx
;;; ------------------------------------
printString:
mov eax, 4
mov ebx, 1
int 0x80
ret
hanoi1.asm
;;; hanoi1.asm
;;; D.T.
;;; Towers of Hanoi, top down...
;;; assumptions:
;;; al = n Number of disk
;;; bl = Source character identifying the source
;;; cl = Dest character identifying the destination
;;; dl = Temp character identifying the extra peg
section .data
moveStr db "X --> X", 10
moveStrLen equ $-moveStr
source equ moveStr + 0
dest equ moveStr + 6
section .text
global _start
;;; ------------------------------------------------------------
;;; M A I N
;;; ------------------------------------------------------------
_start: mov al, 4 ; move 4 disks
mov bl, 'A' ; from A
mov cl, 'B' ; to B
mov dl, 'C' ; using C as extra
call moveDisks
;;; return to OS
mov eax, 1
mov ebx, 0
int 0x80
;;; ------------------------------------------------------------
;;; moveDisks:
;;; assumptions:
;;; al = n Number of disk
;;; bl = Source character identifying the source
;;; cl = Dest character identifying the destination
;;; dl = Temp character identifying the extra peg
;;; Does not return anything
;;; does not modify registers
;;; ------------------------------------------------------------
moveDisks: push ax
push bx
push cx
push dx
mov byte[source], bl
mov byte[dest], cl
call printMove
pop dx
pop cx
pop bx
pop ax
ret
;;; ------------------------------------------------------------
;;; printMove
;;; prints the string moveStr on the screen
;;; ------------------------------------------------------------
printMove: pushad
mov eax, 4
mov ebx, 1
mov ecx, moveStr
mov edx, moveStrLen
int 0x80
popad
ret
hanoi2.asm
;;; hanoi2.asm
;;; D.T.
;;; Towers of Hanoi, top down...
;;; assumptions:
;;; al = n Number of disk
;;; bl = Source character identifying the source
;;; cl = Dest character identifying the destination
;;; dl = Temp character identifying the extra peg
%define N 4 ; number of disks to move
section .data
moveStr db "X X", 10
moveStrLen equ $-moveStr
source equ moveStr + 0
dest equ moveStr + 2
section .text
global _start
;;; ------------------------------------------------------------
;;; M A I N
;;; ------------------------------------------------------------
_start: mov al, N ; move 4 disks
mov bl, 'A' ; from A
mov cl, 'B' ; to B
mov dl, 'C' ; using C as extra
call moveDisks
;;; return to OS
mov eax, 1
mov ebx, 0
int 0x80
;;; ------------------------------------------------------------
;;; moveDisks:
;;; assumptions:
;;; al = n Number of disk
;;; bl = Source character identifying the source
;;; cl = Dest character identifying the destination
;;; dl = Temp character identifying the extra peg
;;; Does not return anything
;;; does not modify registers
;;; ------------------------------------------------------------
moveDisks: push ax
push bx
push cx
push dx
cmp al, 1
ja .recurse
;;; only 1 to move: move from source to dest!
mov byte[source], bl
mov byte[dest], cl
call printMove
jmp .return
.recurse:
;;; move n-1 disk from source to temp
dec al ; al <-- n-1
xchg cl, dl ; swap dest and temp
call moveDisks
xchg cl, dl ; swap back dest and temp
;;; move 1 from source to dest
push ax
mov al, 1
mov byte[source], bl
mov byte[dest], cl
call printMove
pop ax
;;; move n-1 disk from temp to dest
xchg bl, dl ; make temp the source
call moveDisks
.return: pop dx
pop cx
pop bx
pop ax
ret
;;; ------------------------------------------------------------
;;; printMove
;;; prints the string moveStr on the screen
;;; ------------------------------------------------------------
printMove: pushad
mov eax, 4
mov ebx, 1
mov ecx, moveStr
mov edx, moveStrLen
int 0x80
popad
ret
hello2.asm
;;; skel.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs skel.asm
;;; ld -melf_i386 -o skel skel.o
;;; ./skel
;;;
section .data
mesg1 db "------------------------------------------------", 0x0a
mesg1Len equ $-mesg1
mesg2 db "Hello!", 0x0a
mesg2Len equ $-mesg2
section .text
global _start
_start:
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, mesg1
mov edx, mesg1Len
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
hello3.asm
section .data
msg db "Hello", 0x0a, 0x0a
msgLen equ $-msg
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msgLen
int 0x80
;;; exit
mov eax,1
mov ebx,0
int 0x80
hello.asm
;;; helloWorld.asm
;;; D. Thiebaut
;;;
;;; Display "Hello there!" on the screen
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs helloWorld.asm
;;; ld -melf_i386 -o helloWorld helloWorld.o
;;; ./helloWorld
;;;
section .data
Hello db "Hello there!", 10, 10, 10
HelloLen equ $-Hello
section .text
global _start
_start:
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, Hello ; address of message to print
mov edx, HelloLen ; # of chars to print
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
helloMovsb.asm
;;; helloWorld.asm
;;; D. Thiebaut
;;;
;;; Display "Hello there!" on the screen
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs helloWorld.asm
;;; ld -melf_i386 -o helloWorld helloWorld.o
;;; ./helloWorld
;;;
section .data
Hello db "Hello there!", 10, 10, 10
HelloLen equ $-Hello
NewHello db " ", 0, 0, 0
section .text
global _start
_start:
;;; print message
mov esi, Hello
mov edi, NewHello
cld
mov ecx, HelloLen
rep movsb
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, NewHello ; address of message to print
mov edx, HelloLen ; # of chars to print
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
howMuchStack2.asm
;;; hwtest.asm
;;; a simple demo program to test I/O with
;;; a C "wrapper" program
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
msg db "Hello! Please enter an integer number: ",0x00
msg2 db "You have entered ",0x00
x dd 0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ebx, esp
for: mov eax, esp
sub eax, ebx
neg eax
call print_int
call print_nl
sub esp, 100000 ;equivalent to pushing 100,000 bytes
jmp for
ret
howMuchStack.asm
;;; hwtest.asm
;;; a simple demo program to test I/O with
;;; a C "wrapper" program
;; -------------------------
;; data segment
;; -------------------------
section .data
;; -------------------------
;; code area
;; -------------------------
section .text
global _start
_start:
jmp _start
ret
hw12_maze.asm
;;;__ ___ _ _ __ __
;;;\ \ / (_)___(_) |_| \/ | __ _ _______
;;; \ \ / /| / __| | __| |\/| |/ _` |_ / _ \
;;; \ V / | \__ \ | |_| | | | (_| |/ / __/
;;; \_/ |_|___/_|\__|_| |_|\__,_/___\___|
;;;
;;;
;;; Aurelia Moore (c) 2007
;;;
;;; This program takes a maze defined in maze1.dat where the
;;; walls are denoted by # and the empty space defined by
;;; spaces. The maze should be in the variable maze in
;;; maze1.dat, and the number of columns and rows in the maze
;;; in the variables width and height, respectively. It will
;;; then try to find a path through the maze. It will leave
;;; "breadcrumbs" for the path it is trying, and when it discovers
;;; that there are no successful paths from a point, places a v
;;; there.
;;;
;;; To assemble and run:
;;; nasm -f elf -F stabs hw8.asm
;;; gcc -o hw8 driver.c asm_io.o hw8.o
;;; ./hw8
;;; -----------------------------------------------------------------------
;;; ____ _ ____ _ _
;;; | _ \ __ _| |_ __ _ / ___| ___ ___| |_(_) ___ _ __
;;; | | | |/ _` | __/ _` | \___ \ / _ \/ __| __| |/ _ \| '_ \
;;; | |_| | (_| | || (_| | ___) | __/ (__| |_| | (_) | | | |
;;; |____/ \__,_|\__\__,_| |____/ \___|\___|\__|_|\___/|_| |_|
;;;
section .data
maze db "##########################"
width equ $-maze
db " #"
db "# #"
db " #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "##########################"
height equ ($-maze) / width
WRITE equ 4
STDOUT equ 1
;;; clrScreen variables
home db 27,"[2J" ; clear the screen
db 27,"[1;1H" ; ansi sequence to bring
; cursor at position 1,1
homeLen equ $-home
;;; My variables
i dd 0 ;Keeps track of which row we are on
j dd 0 ;Keeps track of which column we are on
fmsg db "Fail! No path found. I think this maze has no exit."
fmsgLen equ $-fmsg
smsg db "Found a path!"
smsgLen equ $-smsg
;;; ____ _ ____ _ _
;;; / ___|___ __| | ___ / ___| ___ ___| |_(_) ___ _ __
;;; | | / _ \ / _` |/ _ \ \___ \ / _ \/ __| __| |/ _ \| '_ \
;;; | |__| (_) | (_| | __/ ___) | __/ (__| |_| | (_) | | | |
;;; \____\___/ \__,_|\___| |____/ \___|\___|\__|_|\___/|_| |_|
;;;
section .text
global _start
_start:
;;Push starting coordinates and call fn
push 1 ;Row 1
push 0 ;Column 0
call visitMaze
jnc none ;if false, skip
call printMaze
call printMazeSuccess
jmp done
none:
call printMazeFail
done:
;; return to O.S.
mov eax, 1
mov ebx, 0
int 0x80
;;; -----------------------------------------------------------------------
;; visitMaze:
;; Takes row then col on stack
;; Checks if it is at an exit. Then checks to E,S,N,W,
;; calling itself and checking for space. If it is @ an exit
;; or recieves true from its recursion, it returns true.
;; If none of its paths are viable (from walls, visited spaces,
;; or paths that do not lead to an exit) it places a v and
;; returns false.
;;; -----------------------------------------------------------------------
visitMaze:
push ebp ;Store old ebp
mov ebp,esp
;; Get row and col # from stack
mov eax,dword[ebp+12]
mov ebx,dword[ebp+8]
call ijoffset ;eax<-offset
mov byte[maze+eax],"." ;Change character to .
mov edx,eax ;copy offset
call printMaze ;print, overwrites eax-ecx
;; Get back row and col #
mov eax,dword[ebp+12] ;row #
mov ebx,dword[ebp+8] ;col #
mov ecx,height ;number of rows
dec ecx ;last row
;; Check for exit conidtions (!start and on 1st or last row or col)
;; exit row?
cmp eax,ecx ;in last row?
je exit
cmp eax,0 ;in 1st row?
je exit
;; exit coulun?
mov ecx,width ;# of Columns
dec ecx ;last columns
cmp ebx,ecx ;in last col?
je exit
cmp ebx,0 ;in 1st col?
jne notExit ;If not, not at an exit
cmp eax,1 ;If are in 1st col, check if entrance
jne exit ;if in 1st col but not row=1, exit
jmp notExit
exit:
jmp true ;If at exit, return true
notExit:
;; try east
east:
mov eax,dword[ebp+12] ;get row
mov ebx,dword[ebp+8] ;get col
inc ebx ;column+1
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to East
cmp al," " ;is it blank
jne south ;if no go to next direction
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
push eax ;row
push ebx ;col
call visitMaze
jnc south ;if visitMaze returns false
jmp true ;if returns true,return true
;; try south
south:
mov eax,dword[ebp+12] ;get row
inc eax ;row+1
mov ebx,dword[ebp+8] ;get col
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to South
cmp al," " ;Is it blank
jne north
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
inc eax ;row+1
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
north:
mov eax,dword[ebp+12] ;get row
dec eax ;row-1
mov ebx,dword[ebp+8] ;get col
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to North
cmp al," " ;Is it blank
jne west
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
dec eax ;row-1
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
west:
mov eax,dword[ebp+12] ;get row
mov ebx,dword[ebp+8] ;get col
dec ebx ;col-1
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to east
cmp al," " ;Is it blank
jne false
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
false:
;;change to v and print
mov eax,dword[ebp+12]
mov ebx,dword[ebp+8]
call ijoffset ;eax<-offset
lea eax, [maze+eax]
mov byte[eax],'v'
call printMaze
;;return 0
clc ;set carry bit = 0 (return false)
pop ebp
ret 8
true:
stc ;set carry = 1 (return true)
pop ebp
ret 8
;;; -----------------------------------------------------------------------
;; printMaze: prints the maze in the maze variable
;; Nothing needs to be passed
;;; -----------------------------------------------------------------------
printMaze:
call killTime
call clrScreen
initfori1:
mov dword[i],0 ;Start at 1st row
mov ecx,height ;Loop once for each row
fori1: push ecx ;Store loop counter
intiforj1:
mov dword[j],0 ;1st column
mov ecx,width ;Loop once for each column
forj1:
push ecx
;; Get ready to call offset fn
mov eax, [i]
mov ebx, [j]
call ijoffset
mov al, byte[maze+eax] ;Get correct character in maze
call print_char
inc dword[j] ;go to next column
pop ecx ;Retrieve loop counter
loop forj1
call print_nl
pop ecx
inc dword[i] ;next row
loop fori1
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
section .data
char db '.'
section .text
print_char:
pushad
mov byte[char], al
mov eax, 4
mov ebx, 1
mov ecx, char
mov edx, 1
int 0x80
popad
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
print_string:
pushad
mov ecx, eax
mov eax, 4
mov ebx, 1
int 0x80
popad
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
print_nl:
push ax
mov al, 0x0a
call print_char
pop ax
ret
;;; -----------------------------------------------------------------------
;; printMazeSuccess: same as printMaze, but replaces v's with
;; spaces and says a path was found
;;; -----------------------------------------------------------------------
printMazeSuccess:
call print_nl
mov eax,smsg
push edx
mov edx,smsgLen
call print_string
pop edx
call print_nl
ret
;;; -----------------------------------------------------------------------
;; printMazeFail: same as printMaze, but replaces anything
;; that is not a # with a space,and says no path was found
;;; -----------------------------------------------------------------------
printMazeFail:
call print_nl
mov eax,fmsg
push edx
mov edx, fmsgLen
call print_string
pop edx
call print_nl
ret
;;; -----------------------------------------------------------------------
;; ijoffset: gets a coordinate in the maze, taking the row # from eax
;; and the column # from ebx, and calculates the
;; appropriate offset and stores it in eax.
;; uses eax, ebx, ecx
;;; -----------------------------------------------------------------------
ijoffset:
mov ecx, width ;Number of columns
mul ecx ;eax<-row # * number of columns
add eax,ebx ;eax<-row# * # of columns + column #
ret
;;; -----------------------------------------------------------------------
;; ------------------------------------------------------
;; clrScreen: clears the screen and brings the cursor
;; to "home" position. This is done by using ANSI sequences
;; that, when sent to the screen, do not actually print
;; anything, but instead modify different things, such as
;; the position of the cursor, the contents of the screen,
;; or other screen-related properties. All ansi sequences
;; start with Ascii 27, which is the ESCape character.
;;; -----------------------------------------------------------------------
clrScreen:
pushad ; save all registers
mov eax,WRITE ; already defined
mov ebx,STDOUT ; already defined
lea ecx,[home]
mov edx,homeLen
int 0x80
popad ; restore all registers
ret
;;; -----------------------------------------------------------------------
;; killTime: performs many additions and subtractions between
;; each visit to make it easier to see each step of the
;; visiting process.
;;; -----------------------------------------------------------------------
killTime:
pushad ;push all 32-bit registers
mov ecx, 50000000
for: mov edx, 1
add edx, 1
sub edx, 1
loop for
popad ;pop all 32-bit registers
ret
hw12_play.asm
;;;__ ___ _ _ __ __
;;;\ \ / (_)___(_) |_| \/ | __ _ _______
;;; \ \ / /| / __| | __| |\/| |/ _` |_ / _ \
;;; \ V / | \__ \ | |_| | | | (_| |/ / __/
;;; \_/ |_|___/_|\__|_| |_|\__,_/___\___|
;;;
;;;
;;; Aurelia Moore (c) 2007
;;;
;;; This program takes a maze defined in maze1.dat where the
;;; walls are denoted by # and the empty space defined by
;;; spaces. The maze should be in the variable maze in
;;; maze1.dat, and the number of columns and rows in the maze
;;; in the variables width and height, respectively. It will
;;; then try to find a path through the maze. It will leave
;;; "breadcrumbs" for the path it is trying, and when it discovers
;;; that there are no successful paths from a point, places a v
;;; there.
;;;
;;; To assemble and run:
;;; nasm -f elf -F stabs hw8.asm
;;; gcc -o hw8 driver.c asm_io.o hw8.o
;;; ./hw8
;;; -----------------------------------------------------------------------
;;; ____ _ ____ _ _
;;; | _ \ __ _| |_ __ _ / ___| ___ ___| |_(_) ___ _ __
;;; | | | |/ _` | __/ _` | \___ \ / _ \/ __| __| |/ _ \| '_ \
;;; | |_| | (_| | || (_| | ___) | __/ (__| |_| | (_) | | | |
;;; |____/ \__,_|\__\__,_| |____/ \___|\___|\__|_|\___/|_| |_|
;;;
section .data
maze db "##########################"
width equ $-maze
db " #"
db "# #"
db " #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "# #"
db "##########################"
height equ ($-maze) / width
WRITE equ 4
STDOUT equ 1
;;; clrScreen variables
home db 27,"[2J" ; clear the screen
db 27,"[1;1H" ; ansi sequence to bring
; cursor at position 1,1
homeLen equ $-home
;;; My variables
i dd 0 ;Keeps track of which row we are on
j dd 0 ;Keeps track of which column we are on
fmsg db "Fail! No path found. I think this maze has no exit."
fmsgLen equ $-fmsg
smsg db "Found a path!"
smsgLen equ $-smsg
firstesp dd 0
;;; ____ _ ____ _ _
;;; / ___|___ __| | ___ / ___| ___ ___| |_(_) ___ _ __
;;; | | / _ \ / _` |/ _ \ \___ \ / _ \/ __| __| |/ _ \| '_ \
;;; | |__| (_) | (_| | __/ ___) | __/ (__| |_| | (_) | | | |
;;; \____\___/ \__,_|\___| |____/ \___|\___|\__|_|\___/|_| |_|
;;;
section .text
global _start
_start:
mov [firstesp],esp
;;Push starting coordinates and call fn
push 1 ;Row 1
push 0 ;Column 0
call visitMaze
jnc none ;if false, skip
call printMaze
call printMazeSuccess
jmp done
none:
call printMazeFail
done:
;; return to O.S.
mov eax, 1
mov ebx, 0
int 0x80
;;; -----------------------------------------------------------------------
;; visitMaze:
;; Takes row then col on stack
;; Checks if it is at an exit. Then checks to E,S,N,W,
;; calling itself and checking for space. If it is @ an exit
;; or recieves true from its recursion, it returns true.
;; If none of its paths are viable (from walls, visited spaces,
;; or paths that do not lead to an exit) it places a v and
;; returns false.
;;; -----------------------------------------------------------------------
visitMaze:
push ebp ;Store old ebp
mov ebp,esp
push eax
mov eax, esp
sub eax, [firstesp]
neg eax
call printReg
pop eax
;; Get row and col # from stack
mov eax,dword[ebp+12]
mov ebx,dword[ebp+8]
call ijoffset ;eax<-offset
mov byte[maze+eax],"." ;Change character to .
mov edx,eax ;copy offset
call printMaze ;print, overwrites eax-ecx
;; Get back row and col #
mov eax,dword[ebp+12] ;row #
mov ebx,dword[ebp+8] ;col #
mov ecx,height ;number of rows
dec ecx ;last row
;; Check for exit conidtions (!start and on 1st or last row or col)
;; exit row?
cmp eax,ecx ;in last row?
je exit
cmp eax,0 ;in 1st row?
je exit
;; exit coulun?
mov ecx,width ;# of Columns
dec ecx ;last columns
cmp ebx,ecx ;in last col?
je exit
cmp ebx,0 ;in 1st col?
jne notExit ;If not, not at an exit
cmp eax,1 ;If are in 1st col, check if entrance
jne exit ;if in 1st col but not row=1, exit
jmp notExit
exit:
jmp true ;If at exit, return true
notExit:
;; try east
east:
mov eax,dword[ebp+12] ;get row
mov ebx,dword[ebp+8] ;get col
inc ebx ;column+1
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to East
cmp al," " ;is it blank
jne south ;if no go to next direction
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
push eax ;row
push ebx ;col
call visitMaze
jnc south ;if visitMaze returns false
jmp true ;if returns true,return true
;; try south
south:
mov eax,dword[ebp+12] ;get row
inc eax ;row+1
mov ebx,dword[ebp+8] ;get col
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to South
cmp al," " ;Is it blank
jne north
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
inc eax ;row+1
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
north:
mov eax,dword[ebp+12] ;get row
dec eax ;row-1
mov ebx,dword[ebp+8] ;get col
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to North
cmp al," " ;Is it blank
jne west
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
dec eax ;row-1
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
west:
mov eax,dword[ebp+12] ;get row
mov ebx,dword[ebp+8] ;get col
dec ebx ;col-1
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to east
cmp al," " ;Is it blank
jne false
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
false:
;;change to v and print
mov eax,dword[ebp+12]
mov ebx,dword[ebp+8]
call ijoffset ;eax<-offset
lea eax, [maze+eax]
mov byte[eax],'v'
call printMaze
;;return 0
clc ;set carry bit = 0 (return false)
pop ebp
ret 8
true:
stc ;set carry = 1 (return true)
pop ebp
ret 8
;;; -----------------------------------------------------------------------
;; printMaze: prints the maze in the maze variable
;; Nothing needs to be passed
;;; -----------------------------------------------------------------------
printMaze:
call killTime
call clrScreen
initfori1:
mov dword[i],0 ;Start at 1st row
mov ecx,height ;Loop once for each row
fori1: push ecx ;Store loop counter
intiforj1:
mov dword[j],0 ;1st column
mov ecx,width ;Loop once for each column
forj1:
push ecx
;; Get ready to call offset fn
mov eax, [i]
mov ebx, [j]
call ijoffset
mov al, byte[maze+eax] ;Get correct character in maze
call print_char
inc dword[j] ;go to next column
pop ecx ;Retrieve loop counter
loop forj1
call print_nl
pop ecx
inc dword[i] ;next row
loop fori1
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
section .data
char db '.'
section .text
print_char:
pushad
mov byte[char], al
mov eax, 4
mov ebx, 1
mov ecx, char
mov edx, 1
int 0x80
popad
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
print_string:
pushad
mov ecx, eax
mov eax, 4
mov ebx, 1
int 0x80
popad
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
print_nl:
push ax
mov al, 0x0a
call print_char
pop ax
ret
;;; -----------------------------------------------------------------------
;; printMazeSuccess: same as printMaze, but replaces v's with
;; spaces and says a path was found
;;; -----------------------------------------------------------------------
printMazeSuccess:
call print_nl
mov eax,smsg
push edx
mov edx,smsgLen
call print_string
pop edx
call print_nl
ret
;;; -----------------------------------------------------------------------
;; printMazeFail: same as printMaze, but replaces anything
;; that is not a # with a space,and says no path was found
;;; -----------------------------------------------------------------------
printMazeFail:
call print_nl
mov eax,fmsg
push edx
mov edx, fmsgLen
call print_string
pop edx
call print_nl
ret
;;; -----------------------------------------------------------------------
;; ijoffset: gets a coordinate in the maze, taking the row # from eax
;; and the column # from ebx, and calculates the
;; appropriate offset and stores it in eax.
;; uses eax, ebx, ecx
;;; -----------------------------------------------------------------------
ijoffset:
mov ecx, width ;Number of columns
mul ecx ;eax<-row # * number of columns
add eax,ebx ;eax<-row# * # of columns + column #
ret
;;; -----------------------------------------------------------------------
;; ------------------------------------------------------
;; clrScreen: clears the screen and brings the cursor
;; to "home" position. This is done by using ANSI sequences
;; that, when sent to the screen, do not actually print
;; anything, but instead modify different things, such as
;; the position of the cursor, the contents of the screen,
;; or other screen-related properties. All ansi sequences
;; start with Ascii 27, which is the ESCape character.
;;; -----------------------------------------------------------------------
clrScreen:
pushad ; save all registers
mov eax,WRITE ; already defined
mov ebx,STDOUT ; already defined
lea ecx,[home]
mov edx,homeLen
int 0x80
popad ; restore all registers
ret
;;; -----------------------------------------------------------------------
;; killTime: performs many additions and subtractions between
;; each visit to make it easier to see each step of the
;; visiting process.
;;; -----------------------------------------------------------------------
killTime:
pushad ;push all 32-bit registers
mov ecx, 50000000
for: mov edx, 1
add edx, 1
sub edx, 1
loop for
popad ;pop all 32-bit registers
ret
hw12_sol.asm
;;;__ ___ _ _ __ __
;;;\ \ / (_)___(_) |_| \/ | __ _ _______
;;; \ \ / /| / __| | __| |\/| |/ _` |_ / _ \
;;; \ V / | \__ \ | |_| | | | (_| |/ / __/
;;; \_/ |_|___/_|\__|_| |_|\__,_/___\___|
;;;
;;;
;;; Aurelia Moore, 2007
;;;
;;; This program takes a maze defined in maze1.dat where the
;;; walls are denoted by # and the empty space defined by
;;; spaces. The maze should be in the variable maze in
;;; maze1.dat, and the number of columns and rows in the maze
;;; in the variables width and height, respectively. It will
;;; then try to find a path through the maze. It will leave
;;; "breadcrumbs" for the path it is trying, and when it discovers
;;; that there are no successful paths from a point, places a v
;;; there. The program will end 2 ways: it finds an exit, or returns
;;; to the entrance to put a v there. If it found an exit, it
;;; removes all v's from to show only the maze and the
;;; breadcrumbs for the succesful path, and notes it has found a
;;; path. If it does not, it prints the maze without v's or
;;; breadcrumbs, and notes that it has failed.
;;;
;;; Each visitMaze puts a net 4 doublewords (16 bytes) on the stack:
;;; the row, column, return address, and stored ebp. During the
;;; execution of visitMaze, up to 40 bytes are added, but they
;;; are removed before the next visitMaze is called. They are the
;;; return address when printMaze is called, the return address
;;; when printMaze calls killTime, and the 8 registers that are
;;; pushed during killTime.
;;;
;;; If there are the 10,485,760 bytes I calculated in hw7 for the
;;; stack, then the 40 bytes that only occur once (they don't
;;; "stack") can be taken off the maximum available for the
;;; recursions. If visitMaze is called and there isn't this amount
;;; available in the stack, it will not succeed in running. So
;;; there are 10,485,720 bytes available for recursions. If there
;;; are 16 bytes used in each recursion, there are 655,357 possible
;;; recursions. This is the number in "open" paths, so not including
;;; bits we've marked with v.
;;; In the worst case scenario, where it visits every space in the
;;; interior of a blank maze and then goes to an exit, it will have
;;; (# of rows - 2) * (# of columns - 2) + 2 recursions. The - 2 to
;;; the rows and columns are for the walls - if they are not there
;;; it will exit. The +2 is for the entrance and exit.
;;; In the best case scenario for no walls, where it goes straight to
;;; the exit, it will have the # of columns recursions (it will go to
;;; the opposit wall in the last column).
;;; In the best case scenario for any maze with interior walls, there
;;; is a wall immediatly east of the entrance, and visitMaze is called
;;; only once.
;;;
;;; To assemble and run:
;;; nasm -f elf -F stabs hw8.asm
;;; gcc -o hw8 driver.c asm_io.o hw8.o
;;; ./hw8
;;; -----------------------------------------------------------------------
;;; ____ _ ____ _ _
;;; | _ \ __ _| |_ __ _ / ___| ___ ___| |_(_) ___ _ __
;;; | | | |/ _` | __/ _` | \___ \ / _ \/ __| __| |/ _ \| '_ \
;;; | |_| | (_| | || (_| | ___) | __/ (__| |_| | (_) | | | |
;;; |____/ \__,_|\__\__,_| |____/ \___|\___|\__|_|\___/|_| |_|
;;;
section .data
%include "maze1.dat"
WRITE equ 4
STDOUT equ 1
;;; clrScreen variables
home db 27,"[2J" ; clear the screen
db 27,"[1;1H" ; ansi sequence to bring
; cursor at position 1,1
homeLen equ $-home
;;; My variables
i dd 0 ;Keeps track of which row we are on
j dd 0 ;Keeps track of which column we are on
fmsg db "Fail! No path found. I think this maze has no exit."
fmsgLen equ $-fmsg
smsg db "Found a path!"
smsgLen equ $-smsg
;;; ____ _ ____ _ _
;;; / ___|___ __| | ___ / ___| ___ ___| |_(_) ___ _ __
;;; | | / _ \ / _` |/ _ \ \___ \ / _ \/ __| __| |/ _ \| '_ \
;;; | |__| (_) | (_| | __/ ___) | __/ (__| |_| | (_) | | | |
;;; \____\___/ \__,_|\___| |____/ \___|\___|\__|_|\___/|_| |_|
;;;
section .text
global _start
_start:
;;Push starting coordinates and call fn
push 1 ;Row 1
push 0 ;Column 0
call visitMaze
jnc none ;if false, skip
call printMazeSuc
jmp done
none:
call printMazeFail
done:
;; return to O.S.
mov eax, 1
mov ebx, 0
int 0x80
;;; -----------------------------------------------------------------------
;; visitMaze:
;; Takes row then col on stack
;; Checks if it is at an exit. Then checks to E,S,N,W,
;; calling itself and checking for space. If it is @ an exit
;; or recieves true from its recursion, it returns true.
;; If none of its paths are viable (from walls, visited spaces,
;; or paths that do not lead to an exit) it places a v and
;; returns false.
;;; -----------------------------------------------------------------------
visitMaze:
push ebp ;Store old ebp
mov ebp,esp
;; Get row and col # from stack
mov eax,dword[ebp+12]
mov ebx,dword[ebp+8]
call ijoffset ;eax<-offset
mov byte[maze+eax],"." ;Change character to .
mov edx,eax ;copy offset
call printMaze ;print, overwrites eax-ecx
;; Get back row and col #
mov eax,dword[ebp+12] ;row #
mov ebx,dword[ebp+8] ;col #
mov ecx,height ;number of rows
dec ecx ;last row
;; Check for exit conidtions (!start and on 1st or last row or col)
;; exit row?
cmp eax,ecx ;in last row?
je exit
cmp eax,0 ;in 1st row?
je exit
;; exit coulun?
mov ecx,width ;# of Columns
dec ecx ;last columns
cmp ebx,ecx ;in last col?
je exit
cmp ebx,0 ;in 1st col?
jne notExit ;If not, not at an exit
cmp eax,1 ;If are in 1st col, check if entrance
jne exit ;if in 1st col but not row=1, exit
jmp notExit
exit:
jmp true ;If at exit, return true
notExit:
;; try east
east:
mov eax,dword[ebp+12] ;get row
mov ebx,dword[ebp+8] ;get col
inc ebx ;column+1
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to East
cmp al," " ;is it blank
jne south ;if no go to next direction
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
push eax ;row
push ebx ;col
call visitMaze
jnc south ;if visitMaze returns false
jmp true ;if returns true,return true
;; try south
south:
mov eax,dword[ebp+12] ;get row
inc eax ;row+1
mov ebx,dword[ebp+8] ;get col
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to South
cmp al," " ;Is it blank
jne north
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
inc eax ;row+1
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
north:
mov eax,dword[ebp+12] ;get row
dec eax ;row-1
mov ebx,dword[ebp+8] ;get col
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to North
cmp al," " ;Is it blank
jne west
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
dec eax ;row-1
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
west:
mov eax,dword[ebp+12] ;get row
mov ebx,dword[ebp+8] ;get col
dec ebx ;col-1
call ijoffset ;eax<-offset
mov al,byte[maze+eax] ;get char to east
cmp al," " ;Is it blank
jne false
;; Prepare to call/recurse
mov eax,dword[ebp+12] ;row
push eax
push ebx ;column
call visitMaze
jc true ;if visitMaze returned true
false:
;;change to v and print
mov eax,dword[ebp+12]
mov ebx,dword[ebp+8]
call ijoffset ;eax<-offset
lea eax, [maze+eax]
mov byte[eax],'v'
call printMaze
;;return 0
clc ;set carry bit = 0 (return false)
pop ebp
ret 8
true:
stc ;set carry = 1 (return true)
pop ebp
ret 8
;;; -----------------------------------------------------------------------
;; printMaze: prints the maze in the maze variable
;; Nothing needs to be passed
;;; -----------------------------------------------------------------------
printMaze:
call killTime
call clrScreen
initfori1:
mov dword[i],0 ;Start at 1st row
mov ecx,height ;Loop once for each row
fori1: push ecx ;Store loop counter
intiforj1:
mov dword[j],0 ;1st column
mov ecx,width ;Loop once for each column
forj1:
push ecx
;; Get ready to call offset fn
mov eax, [i]
mov ebx, [j]
call ijoffset
mov al, byte[maze+eax] ;Get correct character in maze
call print_char
inc dword[j] ;go to next column
pop ecx ;Retrieve loop counter
loop forj1
call print_nl
pop ecx
inc dword[i] ;next row
loop fori1
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
section .data
char db '.'
section .text
print_char:
pushad
mov byte[char], al
mov eax, 4
mov ebx, 1
mov ecx, char
mov edx, 1
int 0x80
popad
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
print_string:
pushad
mov ecx, eax
mov eax, 4
mov ebx, 1
int 0x80
popad
ret
;;; -----------------------------------------------------------------------
;;; -----------------------------------------------------------------------
print_nl:
push ax
mov al, 0x0a
call print_char
pop ax
ret
;;; -----------------------------------------------------------------------
;; printMazeSuc: same as printMaze, but replaces v's with
;; spaces and says a path was found
;;; -----------------------------------------------------------------------
printMazeSuc:
call killTime
call clrScreen
initfori2:
mov dword[i],0 ;Start at 1st row
mov ecx,height ;Loop once for each row
fori2: push ecx ;Store loop counter
intiforj2:
mov dword[j],0 ;1st column
mov ecx,width ;Loop once for each column
forj2:
push ecx
;; Get ready to call offset fn
mov eax, [i]
mov ebx, [j]
call ijoffset
mov al, byte[maze+eax] ;Get correct character in maze
;;If character is v, replace with space
cmp al,'v'
jne print1
mov al,' '
print1:
call print_char
inc dword[j] ;go to next column
pop ecx ;Retrieve loop counter
loop forj2
call print_nl
pop ecx
inc dword[i] ;next row
loop fori2
mov eax,smsg
push edx
mov edx,smsgLen
call print_string
pop edx
call print_nl
ret
;;; -----------------------------------------------------------------------
;; printMazeFail: same as printMaze, but replaces anything
;; that is not a # with a space,and says no path was found
;;; -----------------------------------------------------------------------
printMazeFail:
call killTime
call clrScreen
initfori3:
mov dword[i],0 ;Start at 1st row
mov ecx,height ;Loop once for each row
fori3: push ecx ;Store loop counter
intiforj3:
mov dword[j],0 ;1st column
mov ecx,width ;Loop once for each column
forj3:
push ecx
;; Get ready to call offset fn
mov eax, [i]
mov ebx, [j]
call ijoffset
mov al, byte[maze+eax] ;Get correct character in maze
;;If character is not #, replace with space
cmp al,'#'
je print2
mov al,' '
print2:
call print_char
inc dword[j] ;Go to next column
pop ecx ;Retrieve loop counter
loop forj3
call print_nl
pop ecx
inc dword[i] ;next row
loop fori3
mov eax,fmsg
push edx
mov edx, fmsgLen
call print_string
pop edx
call print_nl
ret
;;; -----------------------------------------------------------------------
;; ijoffset: gets a coordinate in the maze, taking the row # from eax
;; and the column # from ebx, and calculates the
;; appropriate offset and stores it in eax.
;; uses eax, ebx, ecx
;;; -----------------------------------------------------------------------
ijoffset:
mov ecx, width ;Number of columns
mul ecx ;eax<-row # * number of columns
add eax,ebx ;eax<-row# * # of columns + column #
ret
;;; -----------------------------------------------------------------------
;; ------------------------------------------------------
;; clrScreen: clears the screen and brings the cursor
;; to "home" position. This is done by using ANSI sequences
;; that, when sent to the screen, do not actually print
;; anything, but instead modify different things, such as
;; the position of the cursor, the contents of the screen,
;; or other screen-related properties. All ansi sequences
;; start with Ascii 27, which is the ESCape character.
;;; -----------------------------------------------------------------------
clrScreen:
pushad ; save all registers
mov eax,WRITE ; already defined
mov ebx,STDOUT ; already defined
lea ecx,[home]
mov edx,homeLen
int 0x80
popad ; restore all registers
ret
;;; -----------------------------------------------------------------------
;; killTime: performs many additions and subtractions between
;; each visit to make it easier to see each step of the
;; visiting process.
;;; -----------------------------------------------------------------------
killTime:
pushad ;push all 32-bit registers
mov ecx, 50000000
for: mov edx, 1
add edx, 1
sub edx, 1
loop for
popad ;pop all 32-bit registers
ret
hw3b.asm
section .data
msg1 db "CSC231 Assembly", 10, 10
msg1Len equ $-msg1
msg2 db "................", 10
msg2Len equ $-msg2
msg3 db "Fall 2012", 10, 10
msg3Len equ $-msg3
section .text
global _start
_start:
;;; print msg1
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, msg1 ; address of message to print
mov edx, msg1Len ; # of chars to print
int 0x80
;;; print msg2
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, msg2 ; address of message to print
mov edx, msg2Len ; # of chars to print
int 0x80
;;; print msg3
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, msg3 ; address of message to print
mov edx, msg3Len ; # of chars to print
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
hw3c.asm
;;; hw3c.asm
;;;
;;;
;;;
;;;
section .data
msg1 db "I love chocolate", 10
msg1Len equ $-msg1
section .text
global _start
_start:
;;; print original string
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg1Len
int 0x80
;;; put your code here
;;; print modified string
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg1Len
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
hw8asol2.asm
;;; ---------------------------------------------------------
;;; hw8aSol2.asm
;;; D. Thiebaut
;;; 11/13/12
;;; This program uses the library dumpRegs.asm to dump
;;; the contents of the main 6 registers (eax, ebx, ecx,
;;; edx, esi and edi) to the screen. Great for debugging without
;;; a debugger.
;;;
;;; Typical output:
;;; +-----------------+
;;; | eax = 1234 5678 |
;;; | ebx = 55FF 55FF |
;;; | ecx = FEDC BA98 |
;;; | edx = 0000 0000 |
;;; | esi = 1111 2222 |
;;; | edi = 2222 3333 |
;;; +-----------------+
;;; +-----------------+
;;; | eax = 1234 5678 |
;;; | ebx = 55FF 55FF |
;;; | ecx = FEDC BA98 |
;;; | edx = 0000 0000 |
;;; | esi = 1111 2222 |
;;; | edi = 2222 3333 |
;;; +-----------------+
;;;
;;; To assemble, link and run:
;;; nasm -f elf hw8aSol.asm
;;; ld -melf_i386 hw8aSol.o -o hw8aSol
;;; ./hw8aSol
;;; ---------------------------------------------------------
%include "dumpRegs.asm"
section .text
global _start
_start:
;;; Initialize the registers
mov eax, 0x12345678
mov ebx, 0x55FF55FF
mov ecx, 0xFEDCBA98
mov edx, 0x00000000
mov esi, 0x11112222
mov edi, 0x22223333
;;; dump them twice to verify that no registers gets modified...
call dumpRegs
call dumpRegs
;;; exit back to OS
mov ebx, 0
mov eax, 1
int 0x80
hw8asol.asm
;;; ---------------------------------------------------------
;;; hw8aSol.asm
;;; D. Thiebaut
;;; 11/13/12
;;; This program supports several functions that allow the user
;;; to dump the contents of the main 6 registers (eax, ebx, ecx,
;;; edx, esi and edi) to the screen. Great for debugging without
;;; a debugger.
;;;
;;; Typical output:
;;; +-----------------+
;;; | eax = 1234 5678 |
;;; | ebx = 55FF 55FF |
;;; | ecx = FEDC BA98 |
;;; | edx = 0000 0000 |
;;; | esi = 1111 2222 |
;;; | edi = 2222 3333 |
;;; +-----------------+
;;; +-----------------+
;;; | eax = 1234 5678 |
;;; | ebx = 55FF 55FF |
;;; | ecx = FEDC BA98 |
;;; | edx = 0000 0000 |
;;; | esi = 1111 2222 |
;;; | edi = 2222 3333 |
;;; +-----------------+
;;;
;;; To assemble, link and run:
;;; nasm -f elf hw8aSol.asm
;;; ld -melf_i386 hw8aSol.o -o hw8aSol
;;; ./hw8aSol
;;; ---------------------------------------------------------
section .data
hex db "0123456789ABCDEF"
regs db "axbxcxdxsidi"
line db "+-----------------+", 10
string db "| exx = .... .... |", 10
lineLen equ $-string
reg equ string+3
word1 equ string+8
section .text
global _start
_start:
;;; Initialize the registers
mov eax, 0x12345678
mov ebx, 0x55FF55FF
mov ecx, 0xFEDCBA98
mov edx, 0x00000000
mov esi, 0x11112222
mov edi, 0x22223333
;;; dump them twice to verify that no registers gets modified...
call dumpRegs
call dumpRegs
;;; exit back to OS
mov ebx, 0
mov eax, 1
int 0x80
;;; ---------------------------------------------------------
;;; dumpRegs: dumps the contents of the 6 main registers (eax
;;; ebx, ecx, edx, esi and edi) in a box on the screen.
;;; the screen. Does not modify any register
;;; ---------------------------------------------------------
dumpRegs: pushad
;;; put all the registers to print in the stack. The loop
;;; will pop each one, one at a time, once per loop.
push edi
push esi
push edx
push ecx
push ebx
push eax
;;; print top bar
call printBar
;;; prepare to loop 6 times (6 registers )
mov ecx, 6
mov esi, 0
.for pop ebx ;get value of register to convert from stack
push ecx ;save loop counter
lea eax, [regs + esi*2] ;get address of string representing register
mov ax, word [eax] ;ax gets "ax" or "bx" or "cx" or ... "di"
mov word[reg], ax ;modify string with name of register
mov edx, word1 ;edx points to buffer where to store hex digits
;ebx contains register to convert
call storeDWord ;store hex equivalent of ebx in string
mov ecx, string ;print the whole string
mov edx, lineLen
call printInt80
inc esi ;index into register names incremented
pop ecx ;get loop counter back
loop .for
;;; print bottom bar
call printBar
popad
ret
;;; ---------------------------------------------------------
;;; storeDWord: gets
;;; ebx: register to convert
;;; edx: address where to put information
;;; ---------------------------------------------------------
storeDWord: rol ebx, 16 ;bring most sig word in least sig word
call storeWord
inc edx ;make edx skip space in string
rol ebx, 16 ;get lower byte back in least sig pos
call storeWord
ret
;;; ---------------------------------------------------------
;;; storeWord: gets
;;; bx: word to convert
;;; edx: address where to put information. edx incremented by 4
;;; ---------------------------------------------------------
storeWord: rol bx, 8 ;put most sig byte of bx in lower position
call storeByte ;and convert it. Store it in where edx
;points to.
rol bx, 8 ;same with lower nybble
call storeByte
ret
;;; ---------------------------------------------------------
;;; storeByte: gets
;;; bl: byte to convert
;;; edx: address where to store information. edx incremented by 2 automatically
;;; ---------------------------------------------------------
storeByte: push ebx
push eax
rol bl, 4 ;get upper nybble in lower position (LSB)
mov al, bl ;play with al now
and eax, 0x0000000F ;clear all but the least significant nybble
add eax, hex ;get ascii in hex array equivalentn to nybble
mov al, [eax] ;hex digit now in bl
mov byte [edx], al ;store ascii in string
inc edx
rol bl, 4 ;get lower nybble back
mov al, bl ;play with al
and eax, 0x0000000F
add eax, hex
mov al, [eax]
mov byte [edx], al
inc edx
pop eax
pop ebx
ret
;;; ---------------------------------------------------------
;;; printInt80: prints on the screen the string whose address
;;; is in ecx and length in edx.
;;; does not modify registers
;;; ---------------------------------------------------------
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; ---------------------------------------------------------
;;; printBar: prints the horizontal bar
;;; does not modify registers
;;; ---------------------------------------------------------
printBar: push ecx
push edx
mov ecx, line
mov edx, lineLen
call printInt80
pop edx
pop ecx
ret
hw9a.asm
;;; hw9.asm
;;; D. Thiebaut
;;; displays a simple hello msg on the screen using int 0x80,
;; in a loop that goes around "many" times!
;;; To assemble, link and run:
;;;
;;; nasmld hw9
;;;
EXIT equ 1
READ equ 3
WRITE equ 4
STDOUT equ 1
;; -------------------------------------
;; data segment
;; -------------------------------------
section .data
msg db "hello world!",0x0a
MSGLEN equ $-msg
;; -------------------------------------
;; code segment
;; -------------------------------------
section .text
global _start
_start: mov ecx, 0 ; get ready to loop
for: mov eax,WRITE ; print message
mov ebx,STDOUT ; to screen
push ecx
mov ecx,msg ; address of msg
mov edx,MSGLEN ; # chars to print
int 0x80 ; ask os to pring msg
pop ecx
;;; push ecx
loop for
;; exit
mov eax,EXIT ; return to OS
mov ebx,0
int 0x80
hw9.asm
;;; nasm -f elf -F stabs hw9.asm ; ld -melf_i386 -o hw9 hw9.o ; ./hw9
%include "asm_io.inc"
section .data
;; live cells are 1 and dead cells are 0
;; the initial population is 32 out of 78 cells
;; with two buffer cells filled with 0
arr dd 0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0
dd 0,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0
dd 0,0,0,0,0,1,1,0,1,0,1,0,0,0,0,0
dd 1,1,0,0,0,0,1,1,1,1,0,0,1,1,1,0
dd 0,0,0,1,1,1,0,1,0,1,1,0,0,0,0,0
arrStart equ $-arr
;; This array holds the value of the neighbors computed
;; for each cell
vals dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
valsStart equ $-vals
fate dd 0, 1, 0 ;fate of cells with 0, 1 or 2 neighbors
liveDead dd " X " ;look up which char to print based on index
section .text
global asm_main
;;; prints a " " for each dead cell and a "X" for each live one
print_gen:
pushad
popad
ret
;;; Computes the next generation of a cell
new_gen:
push ebp ;save old stack loc
mov ebp, esp
pushad
section .data ;creat temporary n-1 and n+1
tempmin dd 0
tempplus dd 0
section .text
mov eax, [ebp+8] ;chec to see if we are getting the index
inc eax
call print_int
popad
pop ebp
ret 4
asm_main:
mov ecx, 0x4a ;loop for 78 cells
.for:
;; inc ecx ;allow counter to reflect buffer zone
push ecx ;give index to function
call new_gen
;; dec ecx ;;return counter to it's proper value
loop .for
ret
hwtest.asm
;;; hwtest.asm
;;; a simple demo program to test I/O with
;;; a C "wrapper" program
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
msg db "Hello! Please enter an integer number: ",0x00
msg2 db "You have entered ",0x00
x dd 0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov eax,msg ; pass address of the string msg in eax
call print_string ; call a function in asm_io library
; that will print the string msg
call read_int ; call a function that reads an
mov [x], eax ; integer from the keyboard and
; returns it in eax. Save returned
; value in variable x
mov eax,msg2 ; print the string msg2
call print_string ; ("you have entered")
mov eax,[x] ; get integer user entered
call print_int ; pass it via eax and call the
; function specialized in printing
; integer numbers
call print_nl ; call the function that prints
; a new blank line
;; return to C program
ret
lab1.asm
;;; ; program_name.asm
;;; ; your name
;;; ;
;;; ; a description of the program
;;; ;
;;; ; to assemble and run:
;;; ;
;;; ; nasm -f elf -F stabs program.asm
;;; ; ld -o program program.o
;;; ; ./program
;;; ; -------------------------------------------------------------------
;; %include files here...
;;; ------------------------------------------------------------
;;; data areas
;;; ------------------------------------------------------------
section .data
msg db "Welcome to csc231", 10
MSGLEN equ $-msg
;;; ------------------------------------------------------------
;;; code area
;;; ------------------------------------------------------------
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg ; use the same name as the string in the data section
mov edx, MSGLEN ; # of chars in string
int 0x80
;;; exit()
mov eax,1
mov ebx,0
int 0x80 ; final system call
loop1.asm
;;; hwtest.asm
;;; a simple demo program to test I/O with
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ecx, 100
mov eax, 1
for:
call print_int
call print_nl
inc eax
loop for
ret
loop2.asm
;;; hwtest.asm
;;; a simple demo program to test I/O with
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ecx, 100
mov eax, 1
mov ebx, 0
for: add ebx, eax
call print_int
call print_nl
inc eax
loop for
call print_nl
mov eax, ebx
call print_int
ret
loop3.asm
;;; loop3.asm
;;;
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
n1 dd 10
n2 dd 20
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ecx, dword[n2]
sub ecx, dword[n1]
inc ecx
mov eax, dword[n1]
mov ebx, 0
for: add ebx, eax
call print_int
call print_nl
inc eax
loop for
call print_nl
mov eax, ebx
call print_int
ret
loop4.asm
;;; loop4.asm
;;; same as loop1.asm, but prints the
;;; numbers 10 per line.
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
space db " ", 0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
;;; n = 1
;;; for i in range( 1, 11 ): # loops 10 times
;;; for j in range( 1, 11 ): # loops 10 times
;;; print( n, end=" " )
;;; n += 1
;;; print()
;;;
;;; n = 1
mov eax, 1
mov ecx, 10
for1: mov edx, ecx ; save ecx of loop1
mov ecx, 10
for2: call print_int ; print n
mov ebx, eax ; save n
mov eax, space ; print space
call print_string
mov eax, ebx ; restore n
inc eax ; n <- n+1
loop for2
call print_nl
mov ecx, edx
loop for1
call print_nl
ret
loopDemo.asm
;;; skel.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs skel.asm
;;; ld -melf_i386 -o skel skel.o
;;; ./skel
;;;
section .data
;;; put your variables here...
section .text
global _start
_start:
mov ecx, 0
for1: loop for1
loop for1
loop for1
;;; put your code here
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
loopExample.asm
;;; loopExample.asm
;;;a simple demo program to show how to implement a counting loop
;;;Uses the driver.c program as a C "wrapper"
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
count dd 0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ecx, 10 ; get ready to loop 10 times
for: mov eax, dword[count] ; load counter
call print_int ; print it
call print_nl ; new line
inc dword[count] ; increment counter
loop for ; keep looping until done
;; return to C program
ret
manymoves.asm
;;; skel.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs skel.asm
;;; ld -melf_i386 -o skel skel.o
;;; ./skel
;;;
section .data
a db 0
b dw 0
c dd 0
section .text
global _start
_start:
mov eax, 3
mov ax, 3
mov al, 3
mov ah, 3
mov eax, c
mov eax, dword[c]
mov ax, word[b]
mov al, byte[a]
mov ah, byte[a]
mov ebx, 3
mov bx, 3
mov bl, 3
mov bh, 3
mov ebx, c
mov ebx, dword[c]
mov bx, word[b]
mov bl, byte[a]
mov bh, byte[a]
mov al, bl
mov cx, dx
mov edx, ebx
;;; put your code here
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
mickeyMouse.asm
;;; mickeyMouse.asm
;;; D. Thiebaut
;;;
;;; Display "Hello Mickey" on the screen,
;;; followed by 3 line-feeds.
;;;
;;; To assemble, link, and run:
;;;
;;; nasm -f elf -F stabs mickeyMouse.asm
;;; ld -melf_i386 -o mickeyMouse mickeyMouse.o
;;; ./mickeyMouse
;;;
section .data
Hello db "Hello Mickey"
Mouse db " Mouse!"
lflflf db 10, 10, 10
section .text
global _start
_start:
;;; print "Hello Mickey"
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, Hello ; "Hello Mickey"
mov edx, Mouse-Hello ; # char between Mouse and Hello
int 0x80
;;; print 3 line-feed chars
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, lflflf ; address of 3 line-feed chars
mov edx, 3 ; print 3 chars
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
midTerm.asm
;;; hwtest.asm
;;; a simple demo program to test I/O with
;;; a C "wrapper" program
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
msg db "Hello! Please enter an integer number: ",0x00
msg2 db "You have entered ",0x00
x dd 0
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ecx, 10
mov eax, 0
for2: call print_int
mov eax, ecx
dec ecx
loop for2
call print_nl
ret
minilab1.asm
;;; minilab1.asm
;;; D. Thiebaut
;;; prints this string on the screen:
;;;
;;; *********************************
;;; * Welcome to CSC231 *
;;; * Home of the Assembly Language *
;;; *********************************
section .data
msg db "*********************************", 10
db "* Welcome to CSC231 *", 10
db "* Home of the Assembly Language *", 10
db "*********************************", 10, 10
msgLen equ $-msg
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msgLen
int 0x80
;;; exit
mov eax,1
mov ebx,0
int 0x80
minilab1_v1.asm
;;; minilab1.asm
;;; D. Thiebaut
;;; prints this string on the screen:
;;;
;;; *********************************
;;; * Welcome to CSC231 *
;;; * Home of the Assembly Language *
;;; *********************************
section .data
msg db "*********************************", 10
db "* Welcome to CSC231 *", 10
db "* Home of the Assembly Language *", 10
db "*********************************", 10, 10
msgLen equ $-msg
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msgLen
int 0x80
;;; exit
mov eax,1
mov ebx,0
int 0x80
minilab1_v2.asm
;;; minilab1.asm
;;; D. Thiebaut
;;; prints this string on the screen:
;;;
;;; *********************************
;;; * Welcome to CSC231 *
;;; * Home of the Assembly Language *
;;; *********************************
section .data
msg db "*********************************", 10
msgLen1 equ $-msg
db "* Welcome to CSC231 *", 10
db "* Home of the Assembly Language *", 10
msgLen2 equ $-msg
section .text
global _start
_start:
;;; print first 3 lines
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msgLen2
int 0x80
;;; print first line back, to close box
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msgLen1
int 0x80
;;; exit
mov eax,1
mov ebx,0
int 0x80
movStrings1.asm
;;; movString1s.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs movString1s.asm
;;; ld -melf_i386 -o movStrings1 movStrings1.o
;;; ./movStrings1
;;;
section .data
msg1 db "Smith College", 10
msg1Len equ $-msg1
msg2 db ".............", 10
section .text
global _start
_start:
;;; print msg1
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg1Len
int 0x80
;;; print msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
movStrings2.asm
;;; movString1s.asm
;;; D. Thiebaut
;;;
;;; This version copies msg1 to msg2
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs movString1s.asm
;;; ld -melf_i386 -o movStrings2 movStrings2.o
;;; ./movStrings2
;;;
section .data
msg1 db "Smith College", 10
msg1Len equ $-msg1
msg2 db ".............", 10
section .text
global _start
_start:
;;; print msg1
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg1Len
int 0x80
;;; print original msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; copy msg1 into msg2
mov al, byte [msg1]
mov byte[msg2], al
mov al, byte [msg1+1]
mov byte[msg2+1], al
mov al, byte [msg1+2]
mov byte[msg2+2], al
mov al, byte [msg1+3]
mov byte[msg2+3], al
mov al, byte [msg1+4]
mov byte[msg2+4], al
mov al, byte [msg1+5]
mov byte[msg2+5], al
mov al, byte [msg1+6]
mov byte[msg2+6], al
mov al, byte [msg1+7]
mov byte[msg2+7], al
mov al, byte [msg1+8]
mov byte[msg2+8], al
mov al, byte [msg1+9]
mov byte[msg2+9], al
mov al, byte [msg1+10]
mov byte[msg2+10], al
mov al, byte [msg1+11]
mov byte[msg2+11], al
mov al, byte [msg1+12]
mov byte[msg2+12], al
;;; print new msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
movStrings3.asm
;;; movStrings3.asm
;;; D. Thiebaut
;;;
;;; This version copies msg1 to msg2, one word at a time...
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs movString1s.asm
;;; ld -melf_i386 -o movStrings3 movStrings3.o
;;; ./movStrings3
;;;
section .data
msg1 db "Smith College", 10
msg1Len equ $-msg1
msg2 db ".............", 10
section .text
global _start
_start:
;;; print msg1
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg1Len
int 0x80
;;; print original msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; copy msg1 into msg2
mov ax, word [msg1]
mov word[msg2], ax
mov ax, word [msg1+2]
mov word[msg2+2], ax
mov ax, word [msg1+4]
mov word[msg2+4], ax
mov ax, word [msg1+6]
mov word[msg2+6], ax
mov ax, word [msg1+8]
mov word[msg2+8], ax
mov ax, word [msg1+10]
mov word[msg2+10], ax
mov ax, word [msg1+12]
mov word[msg2+12], ax
;;; print new msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
movStrings4.asm
;;; movStrings4.asm
;;; D. Thiebaut
;;;
;;; This version copies msg1 to msg2, one doubleword at a time...
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs movString1s.asm
;;; ld -melf_i386 -o movStrings4 movStrings4.o
;;; ./movStrings4
;;;
;;; ------------------------------------------------------------------
;;; WARNING! This program has a bug! Can you figure out where it is?
;;; Even better, can you expose the bug, as the output of this program
;;; seems correct?
;;; Here's the output:
;;;
;;; Smith College
;;; .............
;;; Smith College
;;;
;;; ------------------------------------------------------------------
section .data
msg1 db "Smith College", 10
msg1Len equ $-msg1
msg2 db ".............", 10
section .text
global _start
_start:
;;; print msg1
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg1Len
int 0x80
;;; print original msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; copy msg1 into msg2
mov eax, dword [msg1]
mov dword[msg2], eax
mov eax, dword [msg1+4]
mov dword[msg2+4], eax
mov eax, dword [msg1+8]
mov dword[msg2+8], eax
mov eax, dword [msg1+12]
mov dword[msg2+12], eax
;;; print new msg2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg1Len
int 0x80
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
printBinary.asm
;;; printBinary.asm
;;; D. Thiebaut
;;; prints a number in binary
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
x dd 0xff55aa11
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
mov ebx, dword[x] ; number to print
mov ecx, 32 ; # of bits
for: shl ebx, 1
mov eax, 0 ; eax <-- 0
;;; xor eax, eax
adc eax, 0 ; eax <-- 0 if no carry, 1 if carry
call print_int
loop for
call print_nl
;; return to C program
ret
printInteger.asm
;;; printInteger.asm
;;; D. Thiebaut
;;;
;;; Display "Hello there!" on the screen
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs helloWorld.asm
;;; ld -melf_i386 -o helloWorld helloWorld.o
;;; ./helloWorld
;;;
section .data
char db 'x'
section .text
global _start
_start:
;;; print message
mov eax, 123456789
call printInt
call printNl
mov eax, -1024
call printInt
call printNl
mov eax, -1
call printInt
call printNl
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; -------------------------------------------------------------
;;; printNl: prints a \n
;;; -------------------------------------------------------------
printNl: pushad
mov byte[char], 10
mov eax, 4
mov ebx, 1
mov ecx, char
mov edx, 1
int 0x80
popad
ret
;;; -------------------------------------------------------------
;;; printInt
;;; gets integer to print in eax and prints it in decimal
;;; -------------------------------------------------------------
printInt: pushad
mov ecx, 0 ;get ready to count digits in number
.for1:
mov edx, 0 ;will divide edx:eax by 10. edx gets 0
mov ebx, 10 ;divisor is 10
div ebx ;edx <-- remainder, eax <-- quotient
push dx ;save remainder between 0 and 9.
inc ecx ;one more digit found
cmp eax, 0 ;is there something left?
jne .for1 ;if yes, go back and get more digits
;;; done finding digits. ecx has the number
;;; of digits, and the stack has the numbers
.for2: pop ax ;get digit between 0 and 9
add al, '0' ;transform into Ascii
mov byte[char], al ;put it in string and print string
mov eax, 4
mov ebx, 1
mov edx, 1
push ecx ;save digit counter
mov ecx, char
int 0x80
pop ecx
loop .for2 ;go back for more digits
popad
ret
printStars2.asm
;;; printStars.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs printStars.asm
;;; ld -melf_i386 -o printStars printStars.o
;;; ./printStars
;;;
section .data
stars db 0x0a, "******************************"
starsLen equ $-stars
addr dd stars
count dd starsLen
section .text
global _start
_start:
mov ecx, dword[count]
for: mov dword[count], ecx
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, starsLen
sub edx, dword[count]
int 0x80
mov ecx, dword[count]
loop for
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
printStars.asm
;;; printStars.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs printStars.asm
;;; ld -melf_i386 -o printStars printStars.o
;;; ./printStars
;;;
section .data
stars db 0x0a, "******************************"
starsLen equ $-stars
addr dd stars
count dd starsLen
section .text
global _start
_start:
mov ecx, dword[count]
for: mov dword[count], ecx
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, dword[count]
int 0x80
mov ecx, dword[count]
loop for
;;; exit
jmp next
next:
mov ebx, 0
mov eax, 1
int 0x80
recursFib2.asm
;;; recurseFib2.asm
;;; D. Thiebaut
;;; A possible solution for Homework 10
;;; Computes the nth term of the Fibonacci sequence using
;;; a (very unefficient) recursive function. In this version
;;; we remove the tail-recursion for 9 levels of the recursion
;;; tree by using a look-up table for the first 9 values of
;;; the Fib series
;;; The amount of stack required is defined by what is pushed
;;; in the stack when the function is called: 3 dwords which
;;; include the return address, plus the stuff the function pushes.
;;; if stopping condition is reached, only ebp is pushed, otherwise
;;; 2 more dwords are pushed.
;;; For N=1, the amount of stack used is 3 + 1 = 4 dwords
;;; For N=2, same: 4 dwords
;;; For N=9, same: 4 dwords
;;; For N=10, 4 + 4 = 8 dwords
;;; For N=11, 4 + 4 + 4 = 12 dwords
;;; For N=n, (n-8) * 4 dwords
;;;
%include "dumpRegs.asm"
section .data
FibTable dd 0,1,1,2,3,5,8,13,21,34,55
section .text
global _start
_start: push eax ; make room
push dword 46 ; compute fib(20)
call fib
pop eax ; get fib(20)
call dumpRegs ; display the registers (in hex)
mov eax, 1
mov ebx, 0
int 0x80
;;; ---------------------------------------------------------------
;;; fib: a recursive function for computing fib(n)=fib(n-1)+fib(n-2)
;;; The tail recursion is cut for n<=9, where a look-up table is used
;;; instead.
;;; Stack:
;;; [ebp+12]: returned value
;;; [ebp+8]: N
;;; [ebp+4]: return address
;;; [ebp]: old ebp
fib: push ebp
mov ebp, esp
;;; ebp+8 is N
;;; ebp+12 is return value
mov eax, [ebp+8] ; get N
cmp eax, 9 ; recurse for N>9
jg .recurse
mov eax, dword[FibTable+eax*4] ;otherwise look up
mov dword [ebp+12], eax ;the result in a table
pop ebp
ret 4
.recurse:
push eax ;make room for return value
dec eax ;N-1
push eax ;pass N-1
call fib ;to fib
;we don't pop the result yet...
mov eax, [ebp+8] ;get N
sub eax, 2 ;N-2
push eax ;make room for result
push eax ;pass N-2
call fib ;call fib
pop eax ;pop result for fib(N-2)
pop ebx ;pop result for fib(N-1)
add eax, ebx ;sum up
mov dword [ebp+12], eax ;put result in stack
pop ebp ;return
ret 4
recursFib.asm
%include "dumpRegs.asm"
section .data
section .text
global _start
_start: push eax ; make room
push dword 10 ; compute fib(20)
call fib
pop eax ; get fib(20)
call dumpRegs
mov eax, 1
mov ebx, 0
int 0x80
fib: push ebp
mov ebp, esp
;;; ebp+8 is N
;;; ebp+12 is return value
mov eax, [ebp+8]
cmp eax, 2
jg .recurse
mov dword [ebp+12], 1
pop ebp
ret 4
.recurse:
push eax
dec eax
push eax
call fib
mov eax, [ebp+8]
sub eax, 2
push eax
push eax
call fib
pop eax
pop ebx
add eax, ebx
mov dword [ebp+12], eax
pop ebp
ret 4
reviewSumTwoVars.asm
;;; reviewSumTwoVars.asm
;;; D. Thiebaut
;;;
;;; in C++
;;; ======
;;;
;;; int a = 2, b = 3, res = 0;
;;; sum( a, b, &res );
;;;
;;; void sum( int x, int y, int* z ) {
;;; *z = x + y;
;;; }
;;;
;;; same code in assembly: look below
;;;
%include "dumpRegs.asm"
section .data
a dd 2
b dd 3
res dd 0
section .text
global _start
_start:
;;; example of passing by value and by reference via registers
;;; ----------------------------------------------------------
mov eax, [a]
mov ebx, [b]
mov ecx, res
call sum1
mov edx, [res]
call dumpRegs
;;; example of passing by value and by reference via the stack
;;; ----------------------------------------------------------
mov dword[res], 0 ;reset what's in res
push dword [a]
push dword [b]
push dword res
call sum2
mov edx, [res]
call dumpRegs
;;; exit
mov eax, 1
mov ebx, 0
int 0x80
;;; ----------------------------------------------------------
;;; sum1: gets 2 values in eax and ecx, and stores their sum
;;; at dword [ecx]
;;; Does not modify registers
;;; ----------------------------------------------------------
sum1: mov [ecx], eax
add [ecx], ebx
ret
;;; ----------------------------------------------------------
;;; sum2: gets 2 values in the stack and a reference and
;;; stores the sum of the values at that reference.
;;; Does not modify registers
;;; ----------------------------------------------------------
sum2: push ebp
mov ebp, esp
push eax
push ebx
mov eax, [ebp + 12]
add eax, [ebp + 16]
mov ebx, [ebp + 8]
mov [ebx], eax
pop ebx
pop eax
pop ebp
ret 3*4
simpleAdd.asm
section .data
a dd 3
b dd 5
result dd 0
section .text
global _start
_start:
nop
nop
mov eax, dword[a]
add eax, dword[b]
mov dword[result], eax
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
skel2.asm
;;; ; program_name.asm
;;; ; your name
;;; ;
;;; ; a description of the program
;;; ;
;;; ; to assemble and run:
;;; ;
;;; ; nasm -f elf -F stabs program.asm
;;; ; ld -o program program.o
;;; ; ./program
;;; ; -------------------------------------------------------------------
;; %include files here...
;;; ------------------------------------------------------------
;;; data areas
;;; ------------------------------------------------------------
section .data
;;; ------------------------------------------------------------
;;; code area
;;; ------------------------------------------------------------
section .text
global _start
_start:
;;; (add your code here!!!!)
;;; exit()
mov eax,1
mov ebx,0
int 0x80 ; final system call
skel.asm
;;; skel.asm
;;; D. Thiebaut
;;;
;;;
;;;
;;; To assemble, link, and run:
;;; nasm -f elf -F stabs skel.asm
;;; ld -melf_i386 -o skel skel.o
;;; ./skel
;;;
section .data
;;; put your variables here...
section .text
global _start
_start:
;;; put your code here
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
sumFloat1.asm
; sumFloat1.asm use "C" printf on float
;
; Assemble: nasm -f elf float1.asm
; Link: gcc -m32 -o float1 float1.o
; Run: ./float1
; Adds x to y and store result in z. Prints
; z using printf.
; This program uses the external printf C function which requires
; a format string defining what to print, and a variable number of
; variables to print.
extern printf ; the C function to be called
SECTION .data ; Data section
msg db "sum = %e",0x0a,0x00
x dd 1.5
y dd 2.5
z dd 0
temp dq 0
SECTION .bss
flttmp: resq 1 ; 64-bit temporary for printing flt1
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
fld dword [x] ; need to convert 32-bit to 64-bit
fld dword [y]
fadd
fst dword [z] ; store sum in z
fstp qword [temp] ; store in 64-bit temp and pop stack top
push dword [temp+4] ; push temp as 2 32-bit words
push dword [temp]
push dword msg ; address of format string
call printf ; Call C function
add esp, 12 ; pop stack 3*4 bytes
mov eax, 1 ; exit code, 0=normal
mov ebx, 0
int 0x80 ;
sumFloat2.asm
; sumFloat1.asm use "C" printf on float
;
; Assemble: nasm -f elf float1.asm
; Link: gcc -m32 -o float1 float1.o
; Run: ./float1
; Adds x to y and store result in z. Prints
; z using printf.
; This program uses the external printf C function which requires
; a format string defining what to print, and a variable number of
; variables to print.
%include "dumpRegs.asm"
extern printf ; the C function to be called
SECTION .data ; Data section
msg db "sum = %e",0x0a,0x00
x dd 1.5
y dd 2.5
z dd 0
temp dq 0
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
fld dword [x] ; need to convert 32-bit to 64-bit
fld dword [y]
fadd
fstp dword [z] ; store sum in z
mov eax, [z]
call dumpRegs ;just to see the binary version of z
fld dword [z] ; transform z in 64-bit word
fstp qword [temp] ; store in 64-bit temp and pop stack top
push dword [temp+4] ; push temp as 2 32-bit words
push dword [temp]
push dword msg ; address of format string
call printf ; Call C function
add esp, 12 ; pop stack 3*4 bytes
mov eax, 1 ; exit code, 0=normal
mov ebx, 0
int 0x80 ;
sumFloat3.asm
; sumFloat3.asm use "C" printf on float
;
; Assemble: nasm -f elf float1.asm
; Link: gcc -m32 -o float1 float1.o
; Run: ./float1
; Compute z = (x-1) * (y+3.5), where x is 1.5 and y is 2.5
; This program uses the external printf C function which requires
; a format string defining what to print, and a variable number of
; variables to print.
%include "dumpRegs.asm"
extern printf ; the C function to be called
SECTION .data ; Data section
msg db "sum = %e",0x0a,0x00
x dd 1.5
y dd 2.5
z dd 0
temp dq 0
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
;;; compute x-1
fld dword [x] ; st0 <- x
fld1 ; st0 <- 1 st1 <- x
fsub ; st0 <- x-1
;;; keep (x-1) in stack and compute y+3.5
fld dword [y] ; st0 <- y st1 <- x-1
push __float32__( 3.5 ) ; put 32-bit float 3.5 in memory (actually in stack)
fld dword [esp] ; st0 <- 3.5 st1 <- y st2 <- x-1
add esp, 4 ; undo push
fadd ; st0 <- y+3.5 st1 <- x-1
fadd ; st0 <- x-1 + y+3.5
fst dword [z] ; store sum in z
fld dword [z] ; transform z in 64-bit word
fstp qword [temp] ; store in 64-bit temp and pop stack top
push dword [temp+4] ; push temp as 2 32-bit words
push dword [temp]
push dword msg ; address of format string
call printf ; Call C function
add esp, 12 ; pop stack 3*4 bytes
mov eax, 1 ; exit code, 0=normal
mov ebx, 0
int 0x80 ;
sumFloat4.asm
; sumFloat4.asm use "C" printf on float
; D. Thiebaut
; Assemble: nasm -f elf sumFloat4.asm
; Link: gcc -m32 -o sumFloat4 sumFloat4.o
; Run: ./sumFloat4
; Compute sum = sum of all the values in the array table.
; This program uses the external printf C function which requires
; a format string defining what to print, and a variable number of
; variables to print.
extern printf ; the C function to be called
SECTION .data ; Data section
table dd 7.36464646465
dd 0.930984158273
dd 10.6047098049
dd 14.3058722306
dd 15.2983812149
dd -17.4394255035
dd -17.8120975978
dd -12.4885670266
dd 3.74178604342
dd 16.3611827165
dd -9.1182728262
dd -11.4055038727
dd 4.68148165048
dd -9.66095817322
dd 5.54394454154
dd 13.4203706426
dd 18.2194407176
dd -7.878340987
dd -6.60045833452
dd -7.98961850398
N equ ($-table)/4 ; number of items in table
;; sum of all the numbers = 10.07955736
msg db "sum = %e",0x0a,0x00
temp dq 0
sum dd 0
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
mov ecx, N
mov ebx, 0
fldz ; st0 <- 0
for: fld dword [table + ebx*4] ; st0 <- new value, st1 <- sum of previous
fadd ; st0 <- sum of new plus previous sum
inc ebx
loop for
;;; get sum back from FPU
fstp dword [sum] ; put final sum in variable
;;; print resulting sum
fld dword [sum] ; transform z in 64-bit word
fstp qword [temp] ; store in 64-bit temp and pop stack top
push dword [temp+4] ; push temp as 2 32-bit words
push dword [temp]
push dword msg ; address of format string
call printf ; Call C function
add esp, 12 ; pop stack 3*4 bytes
mov eax, 1 ; exit code, 0=normal
mov ebx, 0
int 0x80 ;
sumFloat5.asm
; sumFloat5.asm use "C" printf on float
; D. Thiebaut
; Assemble: nasm -f elf sumFloat5.asm
; Link: gcc -m32 -o sumFloat5 sumFloat5.o
; Run: ./sumFloat5
; Compute the max of an array of floats stored in table.
; This program uses the external printf C function which requires
; a format string defining what to print, and a variable number of
; variables to print.
extern printf ; the C function to be called
SECTION .data ; Data section
max dd 0
table dd 7.36464646465
dd 0.930984158273
dd 10.6047098049
dd 14.3058722306
dd 15.2983812149
dd -17.4394255035
dd -17.8120975978
dd -12.4885670266
dd 3.74178604342
dd 16.3611827165
dd -9.1182728262
dd -11.4055038727
dd 4.68148165048
dd -9.66095817322
dd 5.54394454154
dd 13.4203706426
dd 18.2194407176
dd -7.878340987
dd -6.60045833452
dd -7.98961850398
N equ ($-table)/4 ; number of items in table
;; sum of all the numbers = 10.07955736
msg db "max = %e",0x0a,0x00
temp dq 0
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
mov eax, dword [table]
mov dword [max], eax
mov ecx, N-1
mov ebx, 1
fld dword [table] ; st0 <- table[0]
for: fld dword [table + ebx*4] ; st0 <- new value, st1 <- current max
fcom ; compare st0 to st1
fstsw ax ; store fp status in ax
and ax, 100000000b ;
jz newMax
jmp continue
newMax: fxch st1
continue:
fcomp ; pop st0 (don't care about compare)
inc ebx ; point to next fp number
loop for
;;; get sum back from FPU
fstp dword [max] ; st0 is max. Store it in mem
;;; print resulting sum
fld dword [max] ; transform z in 64-bit word
fstp qword [temp] ; store in 64-bit temp and pop stack top
push dword [temp+4] ; push temp as 2 32-bit words
push dword [temp]
push dword msg ; address of format string
call printf ; Call C function
add esp, 12 ; pop stack 3*4 bytes
mov eax, 1 ; exit code, 0=normal
mov ebx, 0
int 0x80 ;
topDown1.asm
;;; towDown.asm
;;; in this version we expand printName
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
mov eax, 4
mov ebx, 1
int 0x80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown2.asm
;;; towDown.asm
;;; in this version we expand printName
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
mov eax, 4
mov ebx, 1
int 0x80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown3.asm
;;; towDown.asm
;;; in this version we expand printName
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown4.asm
;;; towDown.asm
;;; in this version we expand printStars and print a new-line after the name and the line of stars
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneStar db '* '
nl db 0x0a
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
mov ecx, oneStar
mov edx, 1
for: call printInt80
dec al
jnz for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, nl
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown5.asm
;;; towDown.asm
;;; in this version we modify the functions to print extra stars to forma box
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneSpace db ' '
oneStar db '*'
nl db 0x0a
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
add al, 2+2 ; add 2 stars in front and back
mov ecx, oneStar
mov edx, 1 ; print 1 start
for: call printInt80
dec al
jnz for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, nl ; go to the next line
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown6.asm
;;; towDown.asm
;;; in this version we create a loop to print all the boxed names.
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneSpace db ' '
oneStar db '*'
nl db 0x0a
section .text
global _start
_start:
mov ecx, 3
mov eax, strings+0 ; eax <- address count+string
.for: call printBoxName
mov bl, byte[eax] ; bl gets # bytes
and ebx, 0x000000ff ; extend bl in ebx
inc ebx ; add 1 for byte containing #
add eax, ebx ; make eax point to next string
loop .for
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
push eax
mov al, byte[eax] ;al contains 5
call printStars
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
add al, 2+2 ; add 2 stars in front and back
mov ecx, oneStar
mov edx, 1 ; print 1 start
.for: call printInt80
dec al
jnz .for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, nl ; go to the next line
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown7.asm
;;; towDown.asm
;;; in this version we create a loop to print all the boxed names.
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneSpace db ' '
oneStar db '*'
nl db 0x0a
section .text
global _start
_start:
mov ecx, 3
mov eax, strings+0 ; eax <- address count+string
.for: call printBoxName
mov bl, byte[eax] ; bl gets # bytes
and ebx, 0x000000ff ; extend bl in ebx
inc ebx ; add 1 for byte containing #
add eax, ebx ; make eax point to next string
loop .for
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push ecx
push edx
push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
push eax
mov al, byte[eax] ;al contains 5
call printStars
mov ecx, nl ;print extra nl char
mov edx, 1
call printInt80
pop eax
pop edx
pop ecx
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
add al, 2+2 ; add 2 stars in front and back
mov ecx, oneStar
mov edx, 1 ; print 1 start
.for: call printInt80
dec al
jnz .for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, nl ; go to the next line
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown.asm
;;; towDown.asm
;;; in this version we expand printName
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
mov eax, 4
mov ebx, 1
int 0x80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; print message
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, strings ; address of message to print
mov edx, 0 ; # of chars to print
int 0x80
topDown_v1.asm
;;; towDown.asm
;;; only the main program is expanded here.
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
ret
topDown_v2.asm
;;; towDown.asm
;;; in this version we expand printName
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
mov eax, 4
mov ebx, 1
int 0x80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
topDown_v3.asm
;;; towDown.asm
;;; in this version we modify printName and add printInt80
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
printStars:
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
topDown_v4.asm
;;; towDown.asm
;;; in this version we expand printStars and print a new-line after the name and the line of stars
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneStar db '* '
nl db 0x0a
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
mov ecx, oneStar
mov edx, 1
for: call printInt80
dec al
jnz for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, nl
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
topDown_v5.asm
;;; towDown.asm
;;; in this version we modify the functions to print extra stars to form a box
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneSpace db ' '
oneStar db '*'
nl db 0x0a
section .text
global _start
_start:
mov eax, strings+0 ; eax <- address count+string
call printBoxName
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
mov al, byte[eax] ;al contains 5
call printStars
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
add al, 2+2 ; add 2 stars in front and back
mov ecx, oneStar
mov edx, 1 ; print 1 start
for: call printInt80
dec al
jnz for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, nl ; go to the next line
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
topDown_v6.asm
;;; towDown.asm
;;; in this version we create a loop to print all the boxed names.
;;; we also change the "for" labels into ".for" (local labels)
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneSpace db ' '
oneStar db '*'
nl db 0x0a
section .text
global _start
_start:
mov ecx, 3
mov eax, strings+0 ; eax <- address count+string
.for: call printBoxName
mov bl, byte[eax] ; bl gets # bytes
and ebx, 0x000000ff ; extend bl in ebx
inc ebx ; add 1 for byte containing #
add eax, ebx ; make eax point to next string
loop .for
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
push eax
mov al, byte[eax] ;al contains 5
call printStars
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
add al, 2+2 ; add 2 stars in front and back
mov ecx, oneStar
mov edx, 1 ; print 1 start
.for: call printInt80
dec al
jnz .for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, nl ; go to the next line
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
topDown_v7.asm
;;; towDown.asm
;;; in this version we clean up the code.
section .data
strings db 5, "Hello"
db 6, "Sharon"
db 7, "Pamela!"
oneSpace db ' '
oneStar db '*'
nl db 0x0a
section .text
global _start
_start:
mov ecx, 3
mov eax, strings+0 ; eax <- address count+string
.for: call printBoxName
mov bl, byte[eax] ; bl gets # bytes
and ebx, 0x000000ff ; extend bl in ebx
inc ebx ; add 1 for byte containing #
add eax, ebx ; make eax point to next string
loop .for
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName: push ecx
push edx
push eax ;eax contains address of 5
mov al,byte[eax] ;al contains 5
call printStars
pop eax ;address of 5
push eax ;put the address of 5 back in stack
call printName
pop eax ;get back address of 5
push eax
mov al, byte[eax] ;al contains 5
call printStars
mov ecx, nl ;print extra nl char
mov edx, 1
call printInt80
pop eax
pop edx
pop ecx
ret
;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
push eax
push ecx
push edx
add al, 2+2 ; add 2 stars in front and back
mov ecx, oneStar
mov edx, 1 ; print 1 start
.for: call printInt80
dec al
jnz .for
mov ecx, nl
call printInt80
pop edx
pop ecx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax. address of string is at eax+1
;;; Does not modify any registers.
printName:
push eax ; save registers
push ebx
push ecx
push edx
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov dl, byte[eax] ;get # chars in dl
and edx,0x000000ff ;clear upper part of edx (not dl)
inc eax ;eax points to string
mov ecx, eax ;ecx points to string
call printInt80
mov ecx, oneSpace ; print ' '
mov edx, 1
call printInt80
mov ecx, oneStar ; print '*'
mov edx, 1
call printInt80
mov ecx, nl ; go to the next line
mov edx, 1
call printInt80
pop edx ;restore the registers
pop ecx
pop ebx
pop eax
ret
;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80: push eax
push ebx
mov eax, 4
mov ebx, 1
int 0x80
pop ebx
pop eax
ret
C/C++/Java Files
Demo1.java
public class Demo1 {
final static byte START = 0x01;
final static byte PHASE1 = 0x02;
final static byte PHASE2 = 0x04;
final static byte PHASE3 = 0x08;
final static byte DONE = 0x10;
/**
* @param args
*/
public static void main(String[] args) {
byte status = START;
System.out.println( "Status = " + toBinary8( status ) );
for ( int i = 0; i< 100; i++ ) {
if ( Math.random() < 0.1 ) status = (byte) (status | PHASE1);
else if ( Math.random() < 0.1 ) status = (byte) (status ^ PHASE1);
else if ( Math.random() < 0.1 ) status = (byte) (status ^ PHASE2);
else if ( Math.random() < 0.1 ) status = (byte) (status ^ PHASE3);
else if ( Math.random() < 0.1 ) status = (byte) (status ^ DONE);
System.out.println( "Status = " + toBinary8( status ) );
if ( (status & DONE) != 0)
break;
}
}
private static String toBinary8( byte x ) {
return String.format( "%8s", Integer.toBinaryString(x) ).replace(' ', '0');
}
}
driver.c
#include <stdio.h>
extern int asm_main( void );
int main() {
asm_main();
}
FloatingPointStrange2.java
// taken from http://www.lahey.com/float.htm
class FloatingPointStrange2 {
public static void main( String args[] ) {
float x, y;
int c;
x = 8.6f;
y = 1.4f;
c = (int) (x + y);
System.out.println( String.format( "%1.2f + %1.2f = %1.2f = %d", x, y, x+y, c ) );
System.out.println( String.format( "%1.40f + %1.40f = %1.40f = %d", x, y, x+y, c ) );
x = 8.7f;
y = 1.3f;
c = (int) (x + y);
System.out.println( String.format( "%1.2f + %1.2f = %1.2f = %d", x, y, x+y, c ) );
System.out.println( String.format( "%1.40f + %1.40f = %1.40f = %d", x, y, x+y, c ) );
}
}
FloatingPointStrange3.cpp
// taken from http://www.lahey.com/float.htm
#include <iostream>
#include <stdio.h>
using namespace std;
int main( int argc, char *argv[] ) {
double x = 77777.0;
double y = 7.0;
double y1 = 1.0 / y; // 1/7
double z = x / y; // 77777 / 7 = 11111
double z1 = x * y1; // 77777 * 1/7 = 11111
if ( z != z1 ) {
cout << z << " != " << z1 << endl;
printf( "%1.20f != %1.20f\n", z, z1 );
}
else {
cout << z << " == " << z1 << endl;
printf( "%1.20f == %1.20f\n", z, z1 );
}
return 0;
}
FloatingPointStrange3.java
// taken from http://www.lahey.com/float.htm
class DoubleingPointStrange3 {
public static void main( String args[] ) {
double x, y, y1, z, z1;
x = 77777.0;
y = 7.0;
y1 = 1.0 / y; // 1/7
z = x / y; // 77777 / 7 = 10000
z1 = x * y1; // 77777 * 1/7 = 10000
if ( z != z1 ) {
System.out.println( String.format( "%1.3f != %1.3f", z, z1 ) );
System.out.println( String.format( "%1.30f != %1.30f", z, z1 ) );
}
else {
System.out.println( String.format( "%1.3f == %1.3f", z, z1 ) );
System.out.println( String.format( "%1.30f == %1.30f", z, z1 ) );
}
}
}
FloatingPointStrange.cpp
// taken from http://www.lahey.com/float.htm
#include <iostream>
using namespace std;
int main( int argc, char *argv[] ) {
float x = 8.7;
float y = 1.3;
int c = (int) (x+y);
cout << x << " + " << y << " = " << x+y << " c = " << c << endl;
return 0;
}
FloatingPointStrange.java
// taken from http://www.lahey.com/float.htm
class FloatingPointStrange {
public static void main( String args[] ) {
float x = 0.1f;
if ( x * 10.0f != 1.0f )
System.out.println( x + " * 10.0 != 1.0 " );
else
System.out.println( x + " * 10.0 == 1.0 " );
}
}
MultBy3.java
// MultBy3.java
// D. Thiebaut
// A simple program to illustrates what happens when an overflow occurs
// in an int variable.
//
// To compile and run:
// javac MultBy3.java
// java MultBy3
//
public class MultBy3 {
public static void main( String[] args ) {
long a = 2;
for ( int i=0; i<70; i++ ) {
//System.out.println( a );
System.out.println( String.format( "%20d %16s %64s", a , Long.toHexString(a), Long.toBinaryString( a ) ) );
//System.out.println( String.format( "%12d %8s %32s", a , Integer.toHexString(a), Integer.toBinaryString( a ) ) );
a *= 3;
}
}
}
ShiftRight.java
// ShiftRight.java
// D. Thiebaut
// To compile and run:
// javac ShiftRight.java
// java ShiftRight
public class ShiftRight {
public static void main(String[] args) {
for ( int i=-10; i<10; i++ ) {
int a = i >> 2;
int b = i / 2;
System.out.println( "i = " + i + " \ti >> 1 = " + a + " \ti / 2 = " + b );
}
}
}
Python Files
generateTableLookupHexadecimal.py
s = "table\tdb\t"
for i in range(256):
#print "%d %02X" % (i, i )
if ( i!=0 and i%8==0 ):
s += "\n\tdb\t"
else:
if ( i!=0 ):
s += ", "
s += '"%02X"' % i
print s
hanoi2.py
# hanoi.py (Python V 2.7)
# D. Thiebaut
# implements the game of hanoi in python.
# uses recursion.
#
# to run, type
# python hanoi.py
# at the command line
N = 0
def indent( n ):
return (N+1-n)*'| '
def moveDisk( source, dest, extra, n ):
print "%smoveDisk( %s, %s, %s, %d)" % ( indent(n), source, dest, extra, n )
if n==1:
print indent(n-1) + ( "%s --> %s" % ( source, dest ) )
return
# more than 1 disk...
moveDisk( source, extra, dest, n-1)
print indent(n-1) + ( "%s --> %s" % ( source, dest ) )
moveDisk( extra, dest, source, n-1)
def main():
global N
while True:
N = input( "\n\n# of disks? " )
moveDisk( "A", "B", "C", N )
main()
hanoi3.py
# hanoi3.py (Python V 2.7)
# D. Thiebaut
# implements the game of hanoi in python.
# uses recursion and some of the tail recursion
# trimmed at N==2
#
# to run, type
# python hanoi.py
# at the command line
count = 0
def moveDisk( source, dest, extra, n ):
global count
if n>2:
# more than 1 disk...
moveDisk( source, extra, dest, n-1)
#print "move disk from %s to %s" % ( source, dest )
count += 1
moveDisk( extra, dest, source, n-1)
elif n==2:
#print "move disk from %s to %s" % ( source, extra )
#print "move disk from %s to %s" % ( source, dest )
#print "move disk from %s to %s" % ( extra, dest )
count += 3
else:
#print "move disk from %s to %s" % ( source, dest )
count += 1
def main():
global count
while True:
count = 0
n = input( "# of disks? " )
moveDisk( "A", "B", "C", n )
print count, "moves..."
main()
hanoi.py
# hanoi.py (Python V 2.7)
# D. Thiebaut
# implements the game of hanoi in python.
# uses recursion.
#
# to run, type
# python hanoi.py
# at the command line
def moveDisk( source, dest, extra, n ):
if n==1:
print "move disk from %s to %s" % ( source, dest )
return
# more than 1 disk...
moveDisk( source, extra, dest, n-1)
print "move disk from %s to %s" % ( source, dest )
moveDisk( extra, dest, source, n-1)
def main():
while True:
n = input( "# of disks? " )
moveDisk( "A", "B", "C", n )
main()
multBy3.py
# multBy3.py
# D. Thiebaut
# A simple program showing how Python deals with
# integer overflow.
a = 2
for i in range( 700 ):
print a
a = a * 3
Script to Generate This List
#!/bin/bash
echo "=Listings from ~231a/handout="
echo "==Asm Files=="
for file in `ls ~/handout/*.asm ~/handout/*.inc` ; do
#echo $i
echo "===$(basename $file)==="
echo "<br /><source lang=\"asm\">"
cat $file
echo "</source><br /><br />"
done