-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhex2_x86.hex1
620 lines (509 loc) · 26.6 KB
/
hex2_x86.hex1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
# SPDX-FileCopyrightText: © 2017 Jeremiah Orians
#
# SPDX-License-Identifier: GPL-3.0-or-later
## ELF Header
7F 45 4C 46 # e_ident[EI_MAG0-3] ELF's magic number
01 # e_ident[EI_CLASS] Indicating 32 bit
01 # e_ident[EI_DATA] Indicating little endianness
01 # e_ident[EI_VERSION] Indicating original elf
03 # e_ident[EI_OSABI] Set at 3 because FreeBSD is strict
00 # e_ident[EI_ABIVERSION] Set at 0 because none cares
00 00 00 00 00 00 00 # e_ident[EI_PAD]
02 00 # e_type Indicating Executable
03 00 # e_machine Indicating x86
01 00 00 00 # e_version Indicating original elf
54 80 04 08 # e_entry Address of the entry point
34 00 00 00 # e_phoff Address of program header table
00 00 00 00 # e_shoff Address of section header table
00 00 00 00 # e_flags
34 00 # e_ehsize Indicating our 52 Byte header
20 00 # e_phentsize size of a program header table
01 00 # e_phnum number of entries in program table
00 00 # e_shentsize size of a section header table
00 00 # e_shnum number of entries in section table
00 00 # e_shstrndx index of the section names
## Program Header
01 00 00 00 # ph_type: PT-LOAD = 1
00 00 00 00 # ph_offset
00 80 04 08 # ph_vaddr
00 80 04 08 # ph_physaddr
7D 05 00 00 # ph_filesz
00 20 00 00 # ph_memsz
07 00 00 00 # ph_flags: PF-X|PF-W|PF-R = 7
01 00 00 00 # ph_align
# Register usage:
# EAX, EDX, ECX, EBX => Temps
# EDI => IP
# EBP => MALLOC
# ESI => HEAD
# Struct format: (size 24)
# NEXT => 0
# TARGET => 8
# NAME => 16
#:_start
BB 00000000 ; mov_ebx, %0 # Get current pointer
E8 %x ; call %malloc # Get current HEAP
89C3 ; mov_ebx,eax # Using current
89C5 ; mov_ebp,eax # Setup MALLOC
81C3 0000C000 ; addd_ebx, %12582912 # Create space for temp [12M]
E8 %x ; call %malloc # Give ourselves 8192000 bytes to work with
58 ; pop_eax # Get the number of arguments
5B ; pop_ebx # Get the program name
5B ; pop_ebx # Get the actual input name
B9 00000000 ; mov_ecx, %0 # prepare read_only
BA 00000000 ; mov_edx, %0 # Really sure
B8 05000000 ; mov_eax, %5 # the syscall number for open()
CD 80 ; int !0x80 # Now open that damn file
A3 6D850408 ; mov_[DWORD],eax &Input # Preserve the file pointer we were given
5B ; pop_ebx # Get the actual output name
B9 41020000 ; mov_ecx, %577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC
BA C0010000 ; mov_edx, %448 # Prepare file as RWX for owner only (700 in octal)
B8 05000000 ; mov_eax, %5 # the syscall number for open()
CD 80 ; int !0x80 # Now open that damn file
83F8 00 ; cmp_eax, !0 # Check for missing output
0F8F %a ; jg %_start_out # Have real input
B8 01000000 ; mov_eax, %1 # Use stdout
:a #:_start_out
A3 71850408 ; mov_[DWORD],eax &Output # Preserve the file pointer we were given
E8 %I ; call %ClearScratch # Zero scratch
B8 FFFFFFFF ; mov_eax, %-1 # Our flag for byte processing
A3 69850408 ; mov_[DWORD],eax &Flag # Set
B8 00000000 ; mov_eax, %0 # temp storage for the sum
A3 65850408 ; mov_[DWORD],eax &High # Set
BF 00800408 ; mov_edi, %0x8048000 # Our starting IP
BE 00000000 ; mov_esi, %0 # HEAD = NULL
E8 %b ; call %First_pass # Process it
# rewind input file
8B1D 6D850408 ; mov_ebx,[DWORD] &Input # Using our input file
B9 00000000 ; mov_ecx, %0 # Offset Zero
BA 00000000 ; mov_edx, %0 # Whence Zero
B8 13000000 ; mov_eax, %19 # lseek
56 ; push_esi # Protect HEAD
CD 80 ; int !0x80
5E ; pop_esi # Restore HEAD
B8 FFFFFFFF ; mov_eax, %-1 # Our flag for byte processing
A3 69850408 ; mov_[DWORD],eax &Flag # Set
B8 00000000 ; mov_eax, %0 # temp storage for the sum
A3 65850408 ; mov_[DWORD],eax &High # Set
BF 00800408 ; mov_edi, %0x8048000 # Our starting IP
E8 %l ; call %Second_pass # Process it
E9 %w ; jmp %Done
:b #:First_pass
E8 %y ; call %Read_byte
# Deal with EOF
83F8 FC ; cmp_eax, !-4
0F84 %j ; je %First_pass_done
# Check for :
83F8 3A ; cmp_eax, !0x3A
0F85 %c ; jne %First_pass_0
# Deal with label
E9 %D ; jmp %StoreLabel
:c #:First_pass_0
# Check for !
83F8 21 ; cmp_eax, !0x21
0F84 %i ; je %First_pass_pointer
# Check for @
83F8 40 ; cmp_eax, !0x40
0F84 %i ; je %First_pass_pointer
# Check for $
83F8 24 ; cmp_eax, !0x24
0F84 %i ; je %First_pass_pointer
# Check for %
83F8 25 ; cmp_eax, !0x25
0F84 %i ; je %First_pass_pointer
# Check for &
83F8 26 ; cmp_eax, !0x26
0F84 %i ; je %First_pass_pointer
# Deal with everything else
E8 %k ; call %hex # Process our char
# Deal with EOF
83F8 FC ; cmp_eax, !-4
0F84 %j ; je %First_pass_done
# deal with -1 values
83F8 00 ; cmp_eax, !0
0F8C %b ; jl %First_pass
# deal with toggle
A1 69850408 ; mov_eax,[DWORD] &Flag
83F8 00 ; cmp_eax, !0
0F84 %d ; je %First_pass_1
83C7 01 ; add_edi, !1 # Increment IP
:d #:First_pass_1
F7D0 ; not_eax
A3 69850408 ; mov_[DWORD],eax &Flag
E9 %b ; jmp %First_pass
:e #:Update_Pointer
# Check for !
83F8 21 ; cmp_eax, !0x21
0F84 %h ; je %Update_Pointer_1
# Check for @
83F8 40 ; cmp_eax, !0x40
0F84 %g ; je %Update_Pointer_2
# Check for $
83F8 24 ; cmp_eax, !0x24
0F84 %g ; je %Update_Pointer_2
# Check for %
83F8 25 ; cmp_eax, !0x25
0F84 %f ; je %Update_Pointer_4
# Check for &
83F8 26 ; cmp_eax, !0x26
0F84 %f ; je %Update_Pointer_4
# deal with bad input
E8 %R ; call %fail
:f #:Update_Pointer_4
83C7 02 ; add_edi, !2 # Increment IP
:g #:Update_Pointer_2
83C7 01 ; add_edi, !1 # Increment IP
:h #:Update_Pointer_1
83C7 01 ; add_edi, !1 # Increment IP
C3 ; ret
:i #:First_pass_pointer
# Deal with Pointer to label
E8 %e ; call %Update_Pointer # Increment IP
BB 79850408 ; mov_ebx, &table # Using scratch
E8 %B ; call %consume_token # Read token
E8 %I ; call %ClearScratch # Throw away token
83F8 3E ; cmp_eax, !0x3E # check for '>'
0F85 %b ; jne %First_pass # Loop again
# Deal with %label>label case
BB 79850408 ; mov_ebx, &table # Write to scratch
E8 %B ; call %consume_token # get token
E8 %I ; call %ClearScratch # Clean up after ourselves
E9 %b ; jmp %First_pass # Loop again
:j # :First_pass_done
C3 # ret
:k #:hex
# deal with EOF
83F8 FC ; cmp_eax, !-4
0F84 %o ; je %EOF
# deal with line comments starting with #
83F8 23 ; cmp_eax, !0x23
0F84 %t ; je %ascii_comment
# deal with line comments starting with ;
83F8 3B ; cmp_eax, !0x3B
0F84 %t ; je %ascii_comment
# deal all ascii less than 0
83F8 30 ; cmp_eax, !0x30
0F8C %s ; jl %ascii_other
# deal with 0-9
83F8 3A ; cmp_eax, !0x3A
0F8C %p ; jl %ascii_num
# deal with all ascii less than A
83F8 41 ; cmp_eax, !0x41
0F8C %s ; jl %ascii_other
# deal with A-F
83F8 47 ; cmp_eax, !0x47
0F8C %r ; jl %ascii_high
# deal with all ascii less than a
83F8 61 ; cmp_eax, !0x61
0F8C %s ; jl %ascii_other
# deal with a-f
83F8 67 ; cmp_eax, !0x67
0F8C %q ; jl %ascii_low
# The rest that remains needs to be ignored
E9 %s ; jmp %ascii_other
:l #:Second_pass
E8 %y ; call %Read_byte
# Deal with EOF
83F8 FC ; cmp_eax, !-4
0F84 %n ; je %Second_pass_done
# Simply drop the label
83F8 3A ; cmp_eax, !0x3A
0F85 %m ; jne %Second_pass_0
BB 79850408 ; mov_ebx, &table # Using scratch
E8 %B ; call %consume_token # Read token
E8 %I ; call %ClearScratch # Throw away token
E9 %l ; jmp %Second_pass
:m #:Second_pass_0
# Deal with % pointer
83F8 25 ; cmp_eax, !0x25
0F84 %M ; je %StorePointer_rel4
# Deal with @ pointer
83F8 40 ; cmp_eax, !0x40
0F84 %N ; je %StorePointer_rel2
# Deal with ! pointer
83F8 21 ; cmp_eax, !0x21
0F84 %O ; je %StorePointer_rel1
# Deal with & pointer
83F8 26 ; cmp_eax, !0x26
0F84 %P ; je %StorePointer_abs4
# Deal with $ pointer
83F8 24 ; cmp_eax, !0x24
0F84 %Q ; je %StorePointer_abs2
#:Second_pass_1
# Deal with everything else
E8 %k ; call %hex # Process our char
# Deal with EOF
83F8 FC ; cmp_eax, !-4
0F84 %n ; je %Second_pass_done
# deal with -1 values
83F8 00 ; cmp_eax, !0
0F8C %l ; jl %Second_pass
# deal with toggle
8B1D 69850408 ; mov_ebx,[DWORD] &Flag
83FB 00 ; cmp_ebx, !0
0F84 %v ; je %print
# process first byte of pair
C1E0 04 ; shl_eax, !4
A3 65850408 ; mov_[DWORD],eax &High
B8 00000000 ; mov_eax, %0
A3 69850408 ; mov_[DWORD],eax &Flag
E9 %l ; jmp %Second_pass
:n #:Second_pass_done
:o #:EOF
C3 ; ret
:p #:ascii_num
83E8 30 ; sub_eax, !0x30
C3 ; ret
:q #:ascii_low
83E8 57 ; sub_eax, !0x57
C3 ; ret
:r #:ascii_high
83E8 37 ; sub_eax, !0x37
C3 ; ret
:s #:ascii_other
B8 FFFFFFFF ; mov_eax, %-1
C3 ; ret
:t #:ascii_comment
E8 %y ; call %Read_byte
83F8 0D ; cmp_eax, !0xD
0F84 %u ; je %ascii_comment_cr
83F8 0A ; cmp_eax, !0xA
0F85 %t ; jne %ascii_comment
:u #:ascii_comment_cr
B8 FFFFFFFF ; mov_eax, %-1
C3 ; ret
# process second byte of pair
:v #:print
# update the sum and store in output
0305 65850408 ; add_eax,[DWORD] &High
A2 79850408 ; mov_[DWORD],al &table
# Print our first Hex
BA 01000000 ; mov_edx, %1 # set the size of chars we want
E8 %A ; call %print_chars
# flip the toggle
A1 69850408 ; mov_eax,[DWORD] &Flag
F7D0 ; not_eax
A3 69850408 ; mov_[DWORD],eax &Flag
83C7 01 ; add_edi, !1 # Increment IP
E9 %l ; jmp %Second_pass
:w #:Done
# program completed Successfully
BB 00000000 ; mov_ebx, %0 # All is well
B8 01000000 ; mov_eax, %1 # put the exit syscall number in eax
CD 80 ; int !0x80 # Call it a good day
# Malloc isn't actually required if the program being built fits in the initial memory
# However, it doesn't take much to add it.
# Requires a value in EBX
:x #:malloc
B8 2D000000 ; mov_eax, %45 # the Syscall # for SYS_BRK
56 ; push_esi # Protect esi
57 ; push_edi # Protect edi
CD 80 ; int !0x80 # call the Kernel
5F ; pop_edi # Restore edi
5E ; pop_esi # Restore esi
C3 ; ret
:y #:Read_byte
# Attempt to read 1 byte from STDIN
56 ; push_esi # Protect esi
57 ; push_edi # Protect edi
53 ; push_ebx # Protect ebx
51 ; push_ecx # Protect ecx
BA 01000000 ; mov_edx, %1 # set the size of chars we want
B9 75850408 ; mov_ecx, &write # Where to put it
8B1D 6D850408 ; mov_ebx,[DWORD] &Input # Where are we reading from
B8 03000000 ; mov_eax, %3 # the syscall number for read
CD 80 ; int !0x80 # call the Kernel
59 ; pop_ecx # Restore ecx
5B ; pop_ebx # Restore ebx
5F ; pop_edi # Restore edi
5E ; pop_esi # Restore esi
85C0 ; test_eax,eax # check what we got
0F84 %z ; je %Read_byte_1 # Got EOF call it done
# load byte
A0 75850408 ; mov_al,[DWORD] &write # load char
0FB6C0 ; movzx_eax,al # We have to zero extend it to use it
C3 ; ret
# Deal with EOF
:z #:Read_byte_1
B8 FCFFFFFF ; mov_eax, %-4 # Put EOF in eax
C3 ; ret
:A #:print_chars
56 ; push_esi # Protect esi
57 ; push_edi # Protect edi
53 ; push_ebx # Protect ebx
51 ; push_ecx # Protect ecx
B9 79850408 ; mov_ecx, &table # What we are writing
8B1D 71850408 ; mov_ebx,[DWORD] &Output # Write to target file
B8 04000000 ; mov_eax, %4 # the syscall number for write
# edx contains the number of bytes to write
CD 80 ; int !0x80 # call the Kernel
59 ; pop_ecx # Restore ecx
5B ; pop_ebx # Restore ebx
5F ; pop_edi # Restore edi
5E ; pop_esi # Restore esi
C3 ; ret
# Receives pointer in EBX
# Writes out char and updates EBX
:B #:consume_token
E8 %y ; call %Read_byte # Consume_token
# Check for \t
83F8 09 ; cmp_eax, !0x09
0F84 %C ; je %consume_token_done
# Check for \n
83F8 0A ; cmp_eax, !0x0A
0F84 %C ; je %consume_token_done
# Check for ' '
83F8 20 ; cmp_eax, !0x20
0F84 %C ; je %consume_token_done
# Check for '>'
83F8 3E ; cmp_eax, !0x3E
0F84 %C ; je %consume_token_done
# Looks like we are still reading token
8803 ; mov_[ebx],al # Store char
83C3 01 ; add_ebx, !1 # Point to next spot
E9 %B ; jmp %consume_token # loop until done
:C #:consume_token_done
B9 00000000 ; mov_ecx, %0 # Pad with nulls
890B ; mov_[ebx],ecx
83C3 04 ; add_ebx, !4
C3 ; ret
:D #:StoreLabel
89E8 ; mov_eax,ebp # ENTRY
83C5 18 ; add_ebp, !24 # CALLOC
8978 08 ; mov_[eax+BYTE],edi !8 # ENTRY->TARGET = IP
8930 ; mov_[eax],esi # ENTRY->NEXT = JUMP_TABLE
89C6 ; mov_esi,eax # JUMP_TABLE = ENTRY
896E 10 ; mov_[esi+BYTE],ebp !16 # ENTRY->NAME = TOKEN
89EB ; mov_ebx,ebp # Write Starting after struct
E8 %B ; call %consume_token # Collect whole string
89DD ; mov_ebp,ebx # Update HEAP
E9 %b ; jmp %First_pass
:E #:GetTarget
53 ; push_ebx # protect ebx
51 ; push_ecx # protect ecx
52 ; push_edx # protect edx
56 ; push_esi # protect JUMP_TABLE
B9 79850408 ; mov_ecx, &table # Reset scratch
8B56 10 ; mov_edx,[esi+BYTE] !16 # I->NAME
:F #:GetTarget_loop
8A01 ; mov_al,[ecx] # I->NAME[0]
8A1A ; mov_bl,[edx] # scratch[0]
0FB6DB ; movzx_ebx,bl # Zero extend
0FB6C0 ; movzx_eax,al # Zero extend
38D8 ; cmp_al,bl # IF TOKEN == I->NAME
0F85 %G ; jne %GetTarget_miss # Oops
83C1 01 ; add_ecx, !1
83C2 01 ; add_edx, !1
3C 00 ; cmp_al, !0
0F85 %F ; jne %GetTarget_loop # Loop until
E9 %H ; jmp %GetTarget_done # Match
# Miss
:G #:GetTarget_miss
8B36 ; mov_esi,[esi] # I = I->NEXT
83FE 00 ; cmp_esi, !0 # IF NULL == I
0F84 %R ; je %fail # Abort hard
8B56 10 ; mov_edx,[esi+BYTE] !16 # I->NAME
B9 79850408 ; mov_ecx, &table # Reset scratch
E9 %F ; jmp %GetTarget_loop
:H #:GetTarget_done
8B46 08 ; mov_eax,[esi+BYTE] !8 # Get address
5E ; pop_esi # Restore JUMP_TABLE
5A ; pop_edx # Restore edx
59 ; pop_ecx # Restore ecx
5B ; pop_ebx # Restore ebx
C3 ; ret
:I #:ClearScratch
50 ; push_eax # Protect against changes
53 ; push_ebx # And overwrites
51 ; push_ecx # While we work
BB 79850408 ; mov_ebx, &table # Where our table is
B8 00000000 ; mov_eax, %0 # Using null
:J #:ClearScratch_loop
8B0B ; mov_ecx,[ebx] # Get current value
8803 ; mov_[ebx],al # Because we want null
83C3 01 ; add_ebx, !1 # Increment
83F9 00 ; cmp_ecx, !0 # Check if we hit null
0F85 %J ; jne %ClearScratch_loop # Keep looping
59 ; pop_ecx # Restore
5B ; pop_ebx # Damage
58 ; pop_eax # Entirely
C3 ; ret
:K #:StorePointer
E8 %e ; call %Update_Pointer # Increment IP
BB 79850408 ; mov_ebx, &table # Write to scratch
E8 %B ; call %consume_token # get token
50 ; push_eax # Protect base_sep_p
B8 79850408 ; mov_eax, &table # Pointer to scratch
E8 %E ; call %GetTarget # Get address of pointer
E8 %I ; call %ClearScratch # Clean up after ourselves
89FA ; mov_edx,edi # base = IP
5B ; pop_ebx # Restore base_sep_p
83FB 3E ; cmp_ebx, !0x3E # If base_sep_p == '>'
0F85 %L ; jne %StorePointer_done # If not
# Deal with %label>label case
50 ; push_eax # We need to preserve main target
BB 79850408 ; mov_ebx, &table # Write to scratch
E8 %B ; call %consume_token # get token
B8 79850408 ; mov_eax, &table # Pointer to scratch
E8 %E ; call %GetTarget # Get address of pointer
E8 %I ; call %ClearScratch # Clean up after ourselves
89C2 ; mov_edx,eax # Use our new base
58 ; pop_eax # Restore main target
:L #:StorePointer_done
C3 ; ret
:M #:StorePointer_rel4
E8 %K ; call %StorePointer # Do Common
29D0 ; sub_eax,edx # target - ip
A3 79850408 ; mov_[DWORD],eax &table # put value in output
BA 04000000 ; mov_edx, %4 # set the size of chars we want
E8 %A ; call %print_chars
E8 %I ; call %ClearScratch # Clean up after ourselves
E9 %l ; jmp %Second_pass
:N #:StorePointer_rel2
E8 %K ; call %StorePointer # Do Common
29D0 ; sub_eax,edx # target - ip
A3 79850408 ; mov_[DWORD],eax &table # put value in output
BA 02000000 ; mov_edx, %2 # set the size of chars we want
E8 %A ; call %print_chars
E8 %I ; call %ClearScratch # Clean up after ourselves
E9 %l ; jmp %Second_pass
:O #:StorePointer_rel1
E8 %K ; call %StorePointer # Do Common
29D0 ; sub_eax,edx # target - ip
A3 79850408 ; mov_[DWORD],eax &table # put value in output
BA 01000000 ; mov_edx, %1 # set the size of chars we want
E8 %A ; call %print_chars
E8 %I ; call %ClearScratch # Clean up after ourselves
E9 %l ; jmp %Second_pass
:P #:StorePointer_abs4
E8 %K ; call %StorePointer # Do Common
A3 79850408 ; mov_[DWORD],eax &table # put value in output
BA 04000000 ; mov_edx, %4 # set the size of chars we want
E8 %A ; call %print_chars
E8 %I ; call %ClearScratch # Clean up after ourselves
E9 %l ; jmp %Second_pass
:Q #:StorePointer_abs2
E8 %K ; call %StorePointer # Do Common
A3 79850408 ; mov_[DWORD],eax &table # put value in output
BA 02000000 ; mov_edx, %2 # set the size of chars we want
E8 %A ; call %print_chars
E8 %I ; call %ClearScratch # Clean up after ourselves
E9 %l ; jmp %Second_pass
:R #:fail
# Something went wrong
BB 01000000 ; mov_ebx, %1 # All is wrong
B8 01000000 ; mov_eax, %1 # put the exit syscall number in eax
CD 80 ; int !0x80 # Call it a good day
#:High (0x8048565)
00000000 ; %0
#:Flag (0x8048569)
00000000 ; %0
#:Input (0x804856D)
00000000 ; %0
#:Output (0x8048571)
00000000 ; %0
#:write (0x8048575)
00000000 ; %0
#:table (0x8048579)
00000000 ; %0
#:ELF_end