Skip to content

Commit 512eafb

Browse files
committed
Add file handling lessons 22-28.
1 parent 2fdc0a0 commit 512eafb

File tree

24 files changed

+2032
-0
lines changed

24 files changed

+2032
-0
lines changed

code/lesson22/create.asm

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; Create
2+
; Compile with: nasm -f elf create.asm
3+
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 create.o -o create
4+
; Run with: ./create
5+
6+
%include 'functions.asm'
7+
8+
SECTION .data
9+
filename db 'readme.txt', ; the filename to create
10+
11+
SECTION .text
12+
global _start
13+
14+
_start:
15+
16+
mov ecx, 0777 ; set all permissions to read, write, execute
17+
mov ebx, filename ; filename we will create
18+
mov eax, 8 ; invoke SYS_CREAT (kernel opcode 8)
19+
int 80h ; call the kernel
20+
21+
call quit ; call our quit function

code/lesson22/functions.asm

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
;------------------------------------------
2+
; int atoi(Integer number)
3+
; Ascii to integer function (atoi)
4+
atoi:
5+
push ebx ; preserve ebx on the stack to be restored after function runs
6+
push ecx ; preserve ecx on the stack to be restored after function runs
7+
push edx ; preserve edx on the stack to be restored after function runs
8+
push esi ; preserve esi on the stack to be restored after function runs
9+
mov esi, eax ; move pointer in eax into esi (our number to convert)
10+
mov eax, 0 ; initialise eax with decimal value 0
11+
mov ecx, 0 ; initialise ecx with decimal value 0
12+
13+
.multiplyLoop:
14+
xor ebx, ebx ; resets both lower and uppper bytes of ebx to be 0
15+
mov bl, [esi+ecx] ; move a single byte into ebx register's lower half
16+
cmp bl, 48 ; compare ebx register's lower half value against ascii value 48 (char value 0)
17+
jl .finished ; jump if less than to label finished
18+
cmp bl, 57 ; compare ebx register's lower half value against ascii value 57 (char value 9)
19+
jg .finished ; jump if greater than to label finished
20+
cmp bl, 10 ; compare ebx register's lower half value against ascii value 10 (linefeed character)
21+
je .finished ; jump if equal to label finished
22+
cmp bl, 0 ; compare ebx register's lower half value against decimal value 0 (end of string)
23+
jz .finished ; jump if zero to label finished
24+
25+
sub bl, 48 ; convert ebx register's lower half to decimal representation of ascii value
26+
add eax, ebx ; add ebx to our interger value in eax
27+
mov ebx, 10 ; move decimal value 10 into ebx
28+
mul ebx ; multiply eax by ebx to get place value
29+
inc ecx ; increment ecx (our counter register)
30+
jmp .multiplyLoop ; continue multiply loop
31+
32+
.finished:
33+
mov ebx, 10 ; move decimal value 10 into ebx
34+
div ebx ; divide eax by value in ebx (in this case 10)
35+
pop esi ; restore esi from the value we pushed onto the stack at the start
36+
pop edx ; restore edx from the value we pushed onto the stack at the start
37+
pop ecx ; restore ecx from the value we pushed onto the stack at the start
38+
pop ebx ; restore ebx from the value we pushed onto the stack at the start
39+
ret
40+
41+
42+
;------------------------------------------
43+
; void iprint(Integer number)
44+
; Integer printing function (itoa)
45+
iprint:
46+
push eax ; preserve eax on the stack to be restored after function runs
47+
push ecx ; preserve ecx on the stack to be restored after function runs
48+
push edx ; preserve edx on the stack to be restored after function runs
49+
push esi ; preserve esi on the stack to be restored after function runs
50+
mov ecx, 0 ; counter of how many bytes we need to print in the end
51+
52+
.divideLoop:
53+
inc ecx ; count each byte to print - number of characters
54+
mov edx, 0 ; empty edx
55+
mov esi, 10 ; mov 10 into esi
56+
idiv esi ; divide eax by esi
57+
add edx, 48 ; convert edx to it's ascii representation - edx holds the remainder after a divide instruction
58+
push edx ; push edx (string representation of an intger) onto the stack
59+
cmp eax, 0 ; can the integer be divided anymore?
60+
jnz .divideLoop ; jump if not zero to the label divideLoop
61+
62+
.printLoop:
63+
dec ecx ; count down each byte that we put on the stack
64+
mov eax, esp ; mov the stack pointer into eax for printing
65+
call sprint ; call our string print function
66+
pop eax ; remove last character from the stack to move esp forward
67+
cmp ecx, 0 ; have we printed all bytes we pushed onto the stack?
68+
jnz .printLoop ; jump is not zero to the label printLoop
69+
70+
pop esi ; restore esi from the value we pushed onto the stack at the start
71+
pop edx ; restore edx from the value we pushed onto the stack at the start
72+
pop ecx ; restore ecx from the value we pushed onto the stack at the start
73+
pop eax ; restore eax from the value we pushed onto the stack at the start
74+
ret
75+
76+
77+
;------------------------------------------
78+
; void iprintLF(Integer number)
79+
; Integer printing function with linefeed (itoa)
80+
iprintLF:
81+
call iprint ; call our integer printing function
82+
83+
push eax ; push eax onto the stack to preserve it while we use the eax register in this function
84+
mov eax, 0Ah ; move 0Ah into eax - 0Ah is the ascii character for a linefeed
85+
push eax ; push the linefeed onto the stack so we can get the address
86+
mov eax, esp ; move the address of the current stack pointer into eax for sprint
87+
call sprint ; call our sprint function
88+
pop eax ; remove our linefeed character from the stack
89+
pop eax ; restore the original value of eax before our function was called
90+
ret
91+
92+
93+
;------------------------------------------
94+
; int slen(String message)
95+
; String length calculation function
96+
slen:
97+
push ebx
98+
mov ebx, eax
99+
100+
.nextchar:
101+
cmp byte [eax], 0
102+
jz .finished
103+
inc eax
104+
jmp .nextchar
105+
106+
.finished:
107+
sub eax, ebx
108+
pop ebx
109+
ret
110+
111+
112+
;------------------------------------------
113+
; void sprint(String message)
114+
; String printing function
115+
sprint:
116+
push edx
117+
push ecx
118+
push ebx
119+
push eax
120+
call slen
121+
122+
mov edx, eax
123+
pop eax
124+
125+
mov ecx, eax
126+
mov ebx, 1
127+
mov eax, 4
128+
int 80h
129+
130+
pop ebx
131+
pop ecx
132+
pop edx
133+
ret
134+
135+
136+
;------------------------------------------
137+
; void sprintLF(String message)
138+
; String printing with line feed function
139+
sprintLF:
140+
call sprint
141+
142+
push eax
143+
mov eax, 0AH
144+
push eax
145+
mov eax, esp
146+
call sprint
147+
pop eax
148+
pop eax
149+
ret
150+
151+
152+
;------------------------------------------
153+
; void exit()
154+
; Exit program and restore resources
155+
quit:
156+
mov ebx, 0
157+
mov eax, 1
158+
int 80h
159+
ret
160+

code/lesson22/makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FILENAME=create
2+
3+
all: cleanup
4+
nasm -f elf $(FILENAME).asm
5+
ld -m elf_i386 $(FILENAME).o -o $(FILENAME)
6+
./$(FILENAME)
7+
8+
cleanup:
9+
rm -f $(FILENAME).o
10+
rm -f $(FILENAME)
11+
rm -f 'readme.txt'

code/lesson23/functions.asm

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
;------------------------------------------
2+
; int atoi(Integer number)
3+
; Ascii to integer function (atoi)
4+
atoi:
5+
push ebx ; preserve ebx on the stack to be restored after function runs
6+
push ecx ; preserve ecx on the stack to be restored after function runs
7+
push edx ; preserve edx on the stack to be restored after function runs
8+
push esi ; preserve esi on the stack to be restored after function runs
9+
mov esi, eax ; move pointer in eax into esi (our number to convert)
10+
mov eax, 0 ; initialise eax with decimal value 0
11+
mov ecx, 0 ; initialise ecx with decimal value 0
12+
13+
.multiplyLoop:
14+
xor ebx, ebx ; resets both lower and uppper bytes of ebx to be 0
15+
mov bl, [esi+ecx] ; move a single byte into ebx register's lower half
16+
cmp bl, 48 ; compare ebx register's lower half value against ascii value 48 (char value 0)
17+
jl .finished ; jump if less than to label finished
18+
cmp bl, 57 ; compare ebx register's lower half value against ascii value 57 (char value 9)
19+
jg .finished ; jump if greater than to label finished
20+
cmp bl, 10 ; compare ebx register's lower half value against ascii value 10 (linefeed character)
21+
je .finished ; jump if equal to label finished
22+
cmp bl, 0 ; compare ebx register's lower half value against decimal value 0 (end of string)
23+
jz .finished ; jump if zero to label finished
24+
25+
sub bl, 48 ; convert ebx register's lower half to decimal representation of ascii value
26+
add eax, ebx ; add ebx to our interger value in eax
27+
mov ebx, 10 ; move decimal value 10 into ebx
28+
mul ebx ; multiply eax by ebx to get place value
29+
inc ecx ; increment ecx (our counter register)
30+
jmp .multiplyLoop ; continue multiply loop
31+
32+
.finished:
33+
mov ebx, 10 ; move decimal value 10 into ebx
34+
div ebx ; divide eax by value in ebx (in this case 10)
35+
pop esi ; restore esi from the value we pushed onto the stack at the start
36+
pop edx ; restore edx from the value we pushed onto the stack at the start
37+
pop ecx ; restore ecx from the value we pushed onto the stack at the start
38+
pop ebx ; restore ebx from the value we pushed onto the stack at the start
39+
ret
40+
41+
42+
;------------------------------------------
43+
; void iprint(Integer number)
44+
; Integer printing function (itoa)
45+
iprint:
46+
push eax ; preserve eax on the stack to be restored after function runs
47+
push ecx ; preserve ecx on the stack to be restored after function runs
48+
push edx ; preserve edx on the stack to be restored after function runs
49+
push esi ; preserve esi on the stack to be restored after function runs
50+
mov ecx, 0 ; counter of how many bytes we need to print in the end
51+
52+
.divideLoop:
53+
inc ecx ; count each byte to print - number of characters
54+
mov edx, 0 ; empty edx
55+
mov esi, 10 ; mov 10 into esi
56+
idiv esi ; divide eax by esi
57+
add edx, 48 ; convert edx to it's ascii representation - edx holds the remainder after a divide instruction
58+
push edx ; push edx (string representation of an intger) onto the stack
59+
cmp eax, 0 ; can the integer be divided anymore?
60+
jnz .divideLoop ; jump if not zero to the label divideLoop
61+
62+
.printLoop:
63+
dec ecx ; count down each byte that we put on the stack
64+
mov eax, esp ; mov the stack pointer into eax for printing
65+
call sprint ; call our string print function
66+
pop eax ; remove last character from the stack to move esp forward
67+
cmp ecx, 0 ; have we printed all bytes we pushed onto the stack?
68+
jnz .printLoop ; jump is not zero to the label printLoop
69+
70+
pop esi ; restore esi from the value we pushed onto the stack at the start
71+
pop edx ; restore edx from the value we pushed onto the stack at the start
72+
pop ecx ; restore ecx from the value we pushed onto the stack at the start
73+
pop eax ; restore eax from the value we pushed onto the stack at the start
74+
ret
75+
76+
77+
;------------------------------------------
78+
; void iprintLF(Integer number)
79+
; Integer printing function with linefeed (itoa)
80+
iprintLF:
81+
call iprint ; call our integer printing function
82+
83+
push eax ; push eax onto the stack to preserve it while we use the eax register in this function
84+
mov eax, 0Ah ; move 0Ah into eax - 0Ah is the ascii character for a linefeed
85+
push eax ; push the linefeed onto the stack so we can get the address
86+
mov eax, esp ; move the address of the current stack pointer into eax for sprint
87+
call sprint ; call our sprint function
88+
pop eax ; remove our linefeed character from the stack
89+
pop eax ; restore the original value of eax before our function was called
90+
ret
91+
92+
93+
;------------------------------------------
94+
; int slen(String message)
95+
; String length calculation function
96+
slen:
97+
push ebx
98+
mov ebx, eax
99+
100+
.nextchar:
101+
cmp byte [eax], 0
102+
jz .finished
103+
inc eax
104+
jmp .nextchar
105+
106+
.finished:
107+
sub eax, ebx
108+
pop ebx
109+
ret
110+
111+
112+
;------------------------------------------
113+
; void sprint(String message)
114+
; String printing function
115+
sprint:
116+
push edx
117+
push ecx
118+
push ebx
119+
push eax
120+
call slen
121+
122+
mov edx, eax
123+
pop eax
124+
125+
mov ecx, eax
126+
mov ebx, 1
127+
mov eax, 4
128+
int 80h
129+
130+
pop ebx
131+
pop ecx
132+
pop edx
133+
ret
134+
135+
136+
;------------------------------------------
137+
; void sprintLF(String message)
138+
; String printing with line feed function
139+
sprintLF:
140+
call sprint
141+
142+
push eax
143+
mov eax, 0AH
144+
push eax
145+
mov eax, esp
146+
call sprint
147+
pop eax
148+
pop eax
149+
ret
150+
151+
152+
;------------------------------------------
153+
; void exit()
154+
; Exit program and restore resources
155+
quit:
156+
mov ebx, 0
157+
mov eax, 1
158+
int 80h
159+
ret
160+

code/lesson23/makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FILENAME=write
2+
3+
all: cleanup
4+
nasm -f elf $(FILENAME).asm
5+
ld -m elf_i386 $(FILENAME).o -o $(FILENAME)
6+
./$(FILENAME)
7+
8+
cleanup:
9+
rm -f $(FILENAME).o
10+
rm -f $(FILENAME)
11+
rm -f 'readme.txt'

code/lesson23/write.asm

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; Write
2+
; Compile with: nasm -f elf write.asm
3+
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 write.o -o write
4+
; Run with: ./write
5+
6+
%include 'functions.asm'
7+
8+
SECTION .data
9+
filename db 'readme.txt', 0h ; the filename to create
10+
contents db 'Hello world!', 0h ; the contents to write
11+
12+
SECTION .text
13+
global _start
14+
15+
_start:
16+
17+
mov ecx, 0777 ; code continues from lesson 22
18+
mov ebx, filename
19+
mov eax, 8
20+
int 80h
21+
22+
mov edx, 12 ; number of bytes to write - one for each letter of our contents string
23+
mov ecx, contents ; move the memory address of our contents string into ecx
24+
mov ebx, eax ; move the file descriptor of the file we created into ebx
25+
mov eax, 4 ; invoke SYS_WRITE (kernel opcode 4)
26+
int 80h ; call the kernel
27+
28+
call quit ; call our quit function

0 commit comments

Comments
 (0)