How to resolve the algorithm Accumulator factory step by step in the x86 Assembly programming language
How to resolve the algorithm Accumulator factory step by step in the x86 Assembly programming language
Table of Contents
Problem Statement
A problem posed by Paul Graham is that of creating a function that takes a single (numeric) argument and which returns another function that is an accumulator. The returned accumulator function in turn also takes a single numeric argument, and returns the sum of all the numeric values passed in so far to that accumulator (including the initial value passed when the accumulator was created).
The detailed rules are at http://paulgraham.com/accgensub.html and are reproduced here for simplicity (with additions in small italic text).
Create a function that implements the described rules.
It need not handle any special error cases not described above. The simplest way to implement the task as described is typically to use a closure, providing the language supports them. Where it is not possible to hold exactly to the constraints above, describe the deviations.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Accumulator factory step by step in the x86 Assembly programming language
Source code in the x86 programming language
; Accumulator factory
; Returns a function that returns the sum of all numbers ever passed in
; Build:
; nasm -felf32 af.asm
; ld -m elf32_i386 af.o -o af
global _start
section .text
_start:
mov eax, 0x2D ; sys_brk(unsigned long brk)
xor ebx, ebx ; Returns current break on an error
int 0x80 ; syscall
push eax ; Save the initial program break
push 2 ; Get an accumulator initialized to 2
call factory
mov [acc1], eax ; Save the pointer in acc1
push 5 ; Get an accumulator initialized to 5
call factory
mov [acc2], eax ; Save the pointer in acc2
push 4 ; Call acc1 with 4
lea eax, [acc1]
call [eax]
push 4 ; Call acc2 with 4
lea eax, [acc2]
call [eax]
push -9 ; Call acc1 with -9
lea eax, [acc1]
call [eax]
push 13 ; Call acc1 with 13
lea eax, [acc1]
call [eax]
push eax ; Print the number, should be 10
call print_num
push -5 ; Call acc2 with -5
lea eax, [acc2]
call [eax]
push eax ; Print the number, should be 4
call print_num
mov eax, 0x2D ; Reset the program break
pop ebx
int 0x80
mov eax, 0x01 ; sys_exit(int error)
xor ebx, ebx ; error = 0 (success)
int 0x80
; int (*function)(int) factory (int n)
; Returns a pointer to a function that returns the sum of all numbers passed
; in to it, including the initial parameter n;
factory:
push ebp ; Create stack frame
mov ebp, esp
push ebx
push edi
push esi
mov eax, 0x2D ; Allocate memory for the accumulator
xor ebx, ebx
int 0x80
push eax ; Save the current program break
mov ebx, .acc_end ; Calculate the new program break
sub ebx, .acc
push ebx ; Save the length
add ebx, eax
mov eax, 0x2D
int 0x80
pop ecx ; Copy the accumulator code into memory
pop eax ; Set the returned address
mov edi, eax
mov esi, .acc
rep movsb
lea edi, [eax + 10] ; Copy the parameter to initialize accumulator
lea esi, [ebp + 8]
movsd
pop esi ; Tear down stack frame
pop edi
pop ebx
mov esp, ebp
pop ebp
ret 4 ; Return and remove parameter from stack
.acc: ; Start of the returned accumulator
push ebp
mov ebp, esp
push edi
push esi
call .acc_skip ; Jumps over storage, pushing address to stack
dd 0 ; The accumulator storage (32 bits)
.acc_skip:
pop esi ; Retrieve the accumulator using address on stack
lodsd
add eax, [ebp + 8] ; Add the parameter
lea edi, [esi - 4]
stosd ; Save the new value
pop esi
pop edi
mov esp, ebp
pop ebp
ret 4
.acc_end: ; End of accumulator
; void print_num (int n)
; Prints a positive integer and a newline
print_num:
push ebp
mov ebp, esp
mov eax, [ebp + 8] ; Get the number
lea ecx, [output + 10] ; Put a newline at the end
mov BYTE [ecx], 0x0A
mov ebx, 10 ; Divisor
.loop:
dec ecx ; Move backwards in string
xor edx, edx
div ebx
add edx, 0x30 ; Store ASCII digit
mov [ecx], dl
cmp eax, 0 ; Loop until all digits removed
jnz .loop
mov eax, 0x04 ; sys_write(int fd, char *buf, int len)
mov ebx, 0x01 ; stdout
lea edx, [output + 11] ; Calulate length
sub edx, ecx
int 0x80
mov esp, ebp
pop ebp
ret 4
section .bss
acc1: ; Variable that stores the first accumulator
resd 1
acc2: ; Variable that stores the second accumulator
resd 1
output: ; Holds the output buffer
resb 11
You may also check:How to resolve the algorithm Multifactorial step by step in the Picat programming language
You may also check:How to resolve the algorithm Set consolidation step by step in the JavaScript programming language
You may also check:How to resolve the algorithm Arrays step by step in the XPL0 programming language
You may also check:How to resolve the algorithm Play recorded sounds step by step in the BBC BASIC programming language
You may also check:How to resolve the algorithm SEDOLs step by step in the Clojure programming language